Matplotlib重用另一个脚本创建的图形

问题描述 投票:4回答:3

我在Mac上使用Matplotlib和Sublime Text。我使用Python 3.5Matplotlib 2.0

当我处理一个数字时,我通常会有一个绘制数据的脚本,并使用plt.savefig()将该数字保存在.pdf文件中。然后我使用Skim(一个pdf查看器),以便每次修改和运行脚本时刷新文件。这允许我将我的工作布局设置为干净:脚本有一个窗口,一个窗口自动刷新。

我想保持相同的布局,但使用Matplotlib数字(因为它们是交互式的)。我正在寻找一种方法来使用plt.show()但总是在我第一次运行脚本时创建的相同数字中。

例如:

1. First run

import matplotlib.pyplot as plt
import numpy as np 

fig, ax = plt.figure()    

noise = np.random.rand(1, 100)
ax(noise)
plt.show()

2. Following runs

import matplotlib.pyplot as plt
import numpy as np 

# This is the super command I am looking for
fig = plt.get_previous_run_figure()
ax = fig.axes

noise = np.random.rand(1, 100)
ax.plot(noise)
plt.draw()

当然,在这种情况下,我必须与主脚本分开执行首次运行的脚本。有谁知道这是否可能?

python matplotlib
3个回答
3
投票

您希望多个连续的python会话共享一个共同的Matplotlib窗口。我认为无法从单独的进程共享此窗口,尤其是当原始所有者可能在任何时间点终止时。

但是,您可以执行类似于当前工作流的操作,在该工作流中,您有一个外部pdf查看器来查看从多个python实例更新的输出文件。

看到这个问题/答案如何挑选matplotlib图:Store and reload matplotlib.pyplot object

在每个脚本中,输出matplotlib图作为pickle对象,而不是调用plt.show():

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

ax = plt.subplot(111)
x = np.linspace(0, 10)
y = np.exp(x)
plt.plot(x, y)
pickle.dump(ax, file('myplot.pickle', 'w'))

然后,启动一个专用的python会话,加载这个pickle对象并调用plt.show()。让这个脚本循环运行,检查磁盘上pickle文件的更新,并在必要时重新加载:

import matplotlib.pyplot as plt
import pickle

while True:
   ax = pickle.load(file('myplot.pickle'))
   plt.show()

替代

我没有单独的python会话,而是通常只有一个Ipython会话,我在其中运行不同的脚本。通过选择相同的图形窗口,我最终得到了与您描述的大致相似的设置,其中同一个图形窗口全天重复使用。

import matplotlib.pyplot as plt

fig = plt.figure(0)
fig.clf()

plt.show()

0
投票

原则上,可以使用系统范围的剪贴板在两个不同脚本之间建立连接。 (据我所知,windows和macos中的剪贴板是系统范围的。)

因此,想法可以是使用tk或pyqt设置应用程序,并实现通用的FigureCanvas。此应用程序可以为剪贴板中的更改提供事件侦听器。

然后,另一个主工作流脚本将调用一些函数,该函数将当前图形包装到pickle对象中并将其发送到剪贴板,GUI应用程序将从该剪贴板中捕获,并在画布中显示。

这听起来像是一点点工作,但应该满足问题中非常严格的要求。


0
投票

Daan的替代方案为我工作。这里有更多的代码。我在Tkinter交互式GUI中使用它来重用/更新matplotlib图形窗口:

fig1 = None
if fig1:
    #if exists, clear figure 1
    plt.figure(1).clf() 
    plt.suptitle("New Fig Title", fontsize=18, fontweight='bold')
    #reuse window of figure 1 for new figure
    fig1 = plt.scatter(points.T[0], points.T[1], color='red', **plot_kwds)      
else:
    #initialize
    fig1 = plt.figure(num=1,figsize=(7, int(7*imgRatio)), dpi=80)
    plt.tick_params(axis='both', which='major', labelsize=14)
    plt.tick_params(axis='both', which='minor', labelsize=14)           
    plt.suptitle("Title", fontsize=18, fontweight='bold')
    fig1 = plt.scatter(points.T[0], points.T[1], color='red', **plot_kwds)

该图重用了(交互式)plt窗口。为此,我必须在matplotlibrc文件中设置interactive : True(请参阅我的评论here

© www.soinside.com 2019 - 2024. All rights reserved.