【问题标题】:Running a Function That Updates Array While Matplotlib Plots it在 Matplotlib 绘图时运行更新数组的函数
【发布时间】:2016-10-04 03:57:17
【问题描述】:

我有一个 Python 程序 (main.py),它有一个由 RTStreamer 类处理的恒定数据流,它基本上通过实时流获取数据并附加它到一个 numpy 数组。但是,我想实际可视化数据,因为它是 tkinter 和 matplotlib 进来的地方。在另一个 python 文件(gui.py)中,我有一个使用 matplotlib 动画和一个按钮的实时图触发我的第一个文件 (main.py) 开始流式传输数据。但是,当我单击按钮开始流式传输数据时,我可以在控制台上看到它正在获取数据并将其附加到数组中(因为我正在打印数组),但是图表根本没有更新。

这是我的 main.py 的简化版本:

closeBidArray = np.array([])

class RTStreamer(stream.Streamer):
    def __init__(self, *args, **kwargs):
        super(RTStreamer, self).__init__(*args, **kwargs)
        print(datetime.now(), "initialized")

    def on_success(self, data):
        # get data and append it to closeBidArray

    def on_error(self, data):
        # disconnect 

def run():
    stream = RTStreamer()
    stream.rates()

这是我的 gui.py 的样子:

import main # in order to get closeBidArray

figure = Figure(figsize=(5,5), dpi=100)
subplot1 = figure.add_subplot(111)


class App(tk.Tk):
    # Mostly to do with formatting the window and frames in it

def animate():
    subplot1.clear
    subplot1.plot(main.closeBidArray)

class MainPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        # THIS IS THE BUTTON THAT TRIGGERS TO FUNCTION THAT STREAMS THE DATA:
        button1 = tk.Button(text="Hi", command=main.run)
        button1.pack()

        canvas = FigureCanvasTkAgg(figure, self)
        canvas.show()
        canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)

app = App()
ani = animation.FuncAnimation(figure, animate, interval=1000)   
app.mainloop()  

我注意到如果我点击 CTRL+C 来破坏程序,它会遍历流数据并绘制数组,如果我点击 CTRL+C 再次完全关闭 matplotlib 窗口。但是我想在绘制它的同时流式传输并附加到数组,关于如何实现这一点的任何想法?谢谢。

【问题讨论】:

    标签: python python-3.x matplotlib tkinter


    【解决方案1】:

    要使您的代码正常工作,您需要在每一帧上绘制艺术家,而不仅仅是显示画布。但是,这将是缓慢的。您真正想要做的是只更新数据,并保持尽可能多的画布不变。为此,您使用 blit。下面的最小工作示例。

    import numpy as np
    import matplotlib.pyplot as plt
    
    def animate(movie):
        """
        Animate frames in array using blit.
    
        Arguments:
        ----------
            movie: (time, height, width) ndarray
    
        """
    
        plt.ion()
        fig, ax = plt.subplots(1,1)
    
        # initialize blit for movie axis
        img = ax.imshow(np.zeros((movie.shape[1],movie.shape[2])),
                        interpolation = 'nearest', origin = 'lower', vmin = 0, vmax = 1, cmap = 'gray')
    
        # cache the background
        bkg = fig.canvas.copy_from_bbox(ax.bbox)
    
        # loop over frames
        raw_input('Press any key to start the animation...')
        for t in range(movie.shape[0]):
            # draw movie
            img.set_data(movie[t])
            fig.canvas.restore_region(bkg)
            ax.draw_artist(img)
            fig.canvas.blit(ax.bbox)
    
        return
    
    if __name__ == "__main__":
        movie = np.random.rand(1000, 10, 10)
        animate(movie)
        pass
    

    【讨论】:

      猜你喜欢
      • 2019-01-02
      • 2012-06-29
      • 2012-10-01
      • 1970-01-01
      • 2022-01-19
      • 2021-08-22
      • 2022-08-13
      • 1970-01-01
      • 2020-10-26
      相关资源
      最近更新 更多