如何在远程计算机上保存实时数据的图?

时间:2018-04-20 17:22:15

标签: python matplotlib

我想通过sshing和检查图来了解我的模型在进行训练时(即实时数据方式)的作用。

使用animation.FuncAnimation我可以在每次在本地计算机上更新时保存(并覆盖)一帧,如下所示:

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

def animate(i):
    fig.clf()

    plt.suptitle('Title here')

    # actually parse model outputs and plot
    values = np.random.random_integers(0, 100, (100,))
    plt.plot(np.arange(len(values)), values, label='random')
    plt.ylabel('demo data')
    plt.grid()


    plt.legend()
    plt.xlabel('Epochs')
    fig.savefig('Figure.png')


fig = plt.figure()
ani = animation.FuncAnimation(fig, animate, interval=10*60*1000)
plt.show()

在本地计算机上使用此功能很好,因为plt.show调用$ DISPLAY。但是,当在远程服务器上运行时(当然通过ssh),因为没有显示,我得到了RuntimeError: Invalid DISPLAY variable。通过svg使用matplotlib.use('svg')之类的其他后端时。脚本退出而不实际保存任何图像。

另外,我决定在plt.show()函数中使用fig.savefig('Figure.png')animate是因为在调用plt.show()后没有FuncAnimation函数,在给定间隔后不运行animate。我试着改为plt.savefig

关于fig.savefig('Figure.png'),在animate功能之外这样做会导致空白图像。我猜是因为我在animate函数的开头清除了图像。

所以,我的问题是:有没有办法使用animation(或FuncAnimation)在ssh上保存实时数据生成的数据,直到某些事件发生(或者可能是超时)? / p>

4 个答案:

答案 0 :(得分:3)

作为网络服务器建议的替代方案,您可以watch每隔scp秒运行n并将png复制到本地计算机。

类似的东西:

watch -n 5 scp user@remote:/path/to.png ./

将每5秒复制一次文件。

或者使用rsync仅在实际更改时进行复制。 (当文件发生更改时,还有一些实用程序会使用scprsync将其复制到本地计算机。)

答案 1 :(得分:1)

“animation.FuncAnimation”背后的想法是动画函数调用函数来编写/更新图。

您似乎想远程生成“png”文件并通过SSH或其他方式获取。

在两台机器之间共享“无花果”不起作用。

如果您在远程计算机上运行“animate”功能,请移动 fig = plt.figure()进入函数而不是“fig.clf()”

def animate(i):
    fig = plt.figure()

....

虽然可以编写连接到远程计算机的SSH代码,但我可能会在远程服务器上运行一个简单的网络服务器来为每个框架提供服务。

这样你就可以打电话了     http:/// server_frame?index = i加载框架。

如果您是初学者并且没有巨大的性能要求,可以使用cherrypy(https://cherrypy.org/)轻松完成。有关如何提供图片的示例问题,请访问:How to serve multiple matplotlib images from cherrypy?

在本地,您现在可以编写一个新的“get_frame”函数, 下载框架并将其放在本地无花果上。

ani = animation.FuncAnimation(fig, get_frame, interval=10*60*1000)

答案 2 :(得分:1)

老实说,我怀疑使用动画框架是正确的方法。您可以更轻松地将图形保存在自己的循环中,并从ssh查看或使用scp导出。

无论如何,这是代码的解决方法。

首先,您需要使用不需要工作的后端DISPLAYmpl.use('Agg')。

然后,我怀疑动画框架在这种情况下是否有效,它可能使用图形引擎主循环进行绘制。您可以使用MovieWriter。在这里,我使用的是一个最小的电影编写器,只将当前帧保存在png文件中。

请注意interval在这种情况下不起作用,它会保存您生成的每一帧,因此您需要在生成器中自己处理延迟(请参阅下面的丑陋time.sleep(1))。

import numpy as np                                                                                                                                                                    

# headless backend
import matplotlib as mpl                                                                                                                                                              
mpl.use('Agg')

import matplotlib.pyplot as plt                                                                                                                                                       
import matplotlib.animation as animation                                                                                                                                              

import time                                                                                                                                                                           

# dummy movie writer                                                                                                                                                                                          
class NullMovieWriter(animation.AbstractMovieWriter):                                                                                                                                 
    """                                                                                                                                                                               
    from matplotlib/lib/matplotlib/tests/test_animation.py                                                                                                                            
    """                                                                                                                                                                               

    frame_size_can_vary = True                                                                                                                                                        

    def setup(self, fig, outfile, dpi, *args):                                                                                                                                        
        self.fig = fig                                                                                                                                                                
        self.outfile = outfile                                                                                                                                                        
        self.dpi = dpi                                                                                                                                                                
        self.args = args                                                                                                                                                              
        self._count = 0                                                                                                                                                               

    def grab_frame(self, **savefig_kwargs):                                                                                                                                           
        self.savefig_kwargs = savefig_kwargs                                                                                                                                          
        self._count += 1                                                                                                                                                              

        print("saving frame: {}".format(self._count))                                                                                                                                 
        self.fig.savefig(self.outfile)                                                                                                                                                

    def finish(self):                                                                                                                                                                 
        pass                                                                                                                                                                          



fig = plt.figure()                                                                                                                                                                    
def animate(i):                                                                                                                                                                       
    fig.clf()                                                                                                                                                                         

    plt.suptitle('Title here')                                                                                                                                                        

    # actually parse model outputs and plot                                                                                                                                           
    values = np.random.random_integers(0, 100, (100,))                                                                                                                                
    plt.plot(np.arange(len(values)), values, label='random')                                                                                                                          
    plt.ylabel('demo data')                                                                                                                                                           
    plt.grid()                                                                                                                                                                        


    plt.legend()                                                                                                                                                                      
    plt.xlabel('Epochs')                                                                                                                                                              

    time.sleep(1)                                                                                                                                                                     


ani = animation.FuncAnimation(fig, animate, interval=10*60*1000)                                                                                                                      
writer = NullMovieWriter()                                                                                                                                                            
ani.save("Figure.png", writer=writer) 

答案 3 :(得分:1)

也许用纯文本(或pickle)保存日志而不是渲染更容易,每次你想检查它的工作方式时,只需在本地机器上运行一个程序,下载数据和绘图它适合你。

或者,如果你真的想在服务器端渲染它,那么请查看MoviePy库,它可以轻松地与matplotlib集成并渲染gifs。