首页 文章

matplotlib以我希望他们的工作方式为基础

提问于
浏览
0

我不明白如何使用matplotlib创建数字,更新时,阻止时等等 .

To help my understanding and to help me make matplotlib do what I need specifically, could anyone help me create a matplotlib.figure wrapper/almost-clone, let's call it MyFigure, that behaves exactly as described in the code (and its comments) below?

X=[0,1]
Y=[0,1]
Y2a=[0,2]
Y2b=[0,2.5]
Y3a=[0,3]
Y3b=[0,3.5]
Y4=[0,4]

fig = MyFigure() # Nothing happens
ax=fig.gca() # Nothing happens
ax.plot(X,Y) # Nothing happens
fig.show() # New window (1) appears and shows plot of X,Y; execution continues directly
ax.set_xlabel('X') # Window 1 gets X axis label
ax.set_ylabel('Y') # Window 1 gets Y axis label
fig.hide() # Window 1 disappears
time.sleep(10) # No open windows for 10 seconds 
fig.show() # Window 1 reappears and looks the same as before

fig2 = MyFigure() # Nothing happens
fig2.show() # New window (2) appears and is empty
ax2 = fig2.gca() # Window 2 shows axes
ax2.plot(X,Y2a) # Window 2 shows X,Y2a
fig2.show() # Nothing happens, could be omitted
time.sleep(60) # Long computation. In the meantime, windows 1 and 2 can still be resized and their controls (zoom etc.) can be used
ax2.plot(X,Y2b) # Window 2 shows X,Y2a as well as X,Y2b
fig2.hide() # Window 2 disappears

fig3 = MyFigure() # Nothing happens
ax3 = fig3.gca() # Nothing happens
ax3.plot(X,Y3a) # Nothing happens 
fig3.show() # Window 3 appears and shows plot of X,Y3a; execution continues
fig3.freeze() # Nothing happens, Window 3 is still open and can be manipulated
ax3.set_xlabel('X') # Nothing happens
ax3.set_ylabel('Y') # Nothing happens
fig3.thaw() # Window 3 gets X and Y axis labels 
fig3.clear() # Window 3 is still open but empty
ax3 = fig3.gca() # Window 3 shows empty axes
ax3.plot(X,Y3b) # Window 3 shows plot of X,Y3b

fig4 = MyFigure() # Nothing happens 
ax4 = fig4.gca() # Nothing happens 
ax4.plot(X,Y4) # Nothing happens
fig4.show(block=True) # Window 4 opens and shows X,Y4. Execution pauses 
print('Window 4 was closed by user') # Happens after user closes window 4
fig4.show() # Window 4 reappears and looks as before
fig4.close() # Window 4 disappears and its resources are freed
try:
   fig4.show()
except Exception:
   print('Something went wrong') # Prints 'Something went wrong'

# Windows 1,2,3 still "exist". 
# Window 2 is not visible but could be manipulated and shown again in later code.
# Windows 1 and 3 are still visible and can be manipulated by the user. 
# They disappear as soon as the objects fig and fig3 are garbage collected, 
# or their `hide` or `close` methods are called.

请注意,对 MyFigure().show() 的调用可以执行您需要的任何操作,以便按照我的描述使事情正常工作,我只使用了 show 这个词,因为它类似于 plt.show 已经执行的操作 . 我听说过至少有三种方法可以帮助解决我想要的关于交互性的一些方法( plt.ion()fig.show(block=False)plt.draw() ;如果算上 ipython 's magic commands, which I don'打算使用三个半),但这些方法都不能像我一样完全正常工作'd hope and I don' t真正理解其中任何一个背后的逻辑模型 . 对于我失败的尝试,请参阅此问题的底部 .

我不想讨论或批评matplotlib数字及其方法默认工作的方式 . 我确信它们的工作方式有充分的理由,技术和功能,但它与我的直觉完全不兼容(从其他地方没有真正的GUI体验),我在任何时候使用它之前都会对它感到沮丧学习除简单绘图命令之外的任何东西 . 我希望改变这一点 .

基本上,我想 MyFigure 实例表示具有两个重要布尔实例变量的线程: visiblefrozen . 第一个确定打开的窗口是否与实例关联,并且可以由 show()hide() 设置;第二个控制是将更改(例如新图)立即添加到绘图区域还是添加到队列,并且可以由 freeze()thaw() 设置 .

只有当用户(或访问MyFigure实例的另一个线程)关闭相应的窗口时,调用 show(block=False) 才会返回 . 无论 visible 的当前值如何都可以调用它,并且会产生 visible=False . 调用 thaw() 会设置 frozen=False 并将更改队列应用到图中(即使在 visible=False 时也可以应用,但在该状态下冻结和解冻图形是没有意义的,除非该图在另一个线程中被操纵与此同时) .

对我来说最重要的是 show() 的行为和实例的交互行为;我主要描述了 freeze 行为,期待在我的设置中如何处理该用例的问题 . 我不喜欢 ax=fig.gca() 的行为,并且会对 fig.add(matplotlib.Axes()) 这样的事情感觉更好但是's not relevant to this question (besides, I'我有信心我可以自己解决这个问题 .


为了澄清我的挣扎,让我记录到目前为止失败的尝试:

plt.ion()

我在前面加上代码

def MyFigure(): 
    plt.ion()
    return plt.figure()

我评论第一块并继续 fig2 = ... . 当执行命中 time.sleep(60) 时,没有打开的窗口持续60秒 .

fig.show(block=False)

这是我第一次写这篇文章的笔记本电脑,但是在较新版本的matplotlib中似乎删除了block关键字

plt.draw()

这同样影响所有数字 . 尝试将 draw 作为 fig 的实例方法调用__导致 TypeError: draw_wrapper() missing 1 required positional argument: 'renderer' .

暂时忽略这个问题, plt.draw() 本身并没有做任何事情 . 基于一些互联网研究,我发现随后 plt.pause(0.01) 做了我想要的 . 这实际上是最接近我想要的解决方案 . 如果我将所有 fig.show() 替换为 plt.draw();plt.pause(0.01) ,则阻止两个完全符合要求(忽略最终的 fig.hide() ),但它似乎超出丑陋并且似乎不是互联网推荐的 .


(对于潜在的亲密选民:我可以为代码中的每一行制定一些具体问题 . 但是,我觉得所有期望的行为都是(a)相关的足以一起呈现(b)在表格中最好的描述希望与我希望它没有的评论一起写的代码 . )

2 回答

  • 0

    说实话,我觉得matplotlib教程在网络上的挫败感以及在实践中如何使用它 . 当我开始在面向对象的方法中使用它时,个人很多matplotlib挫折消失了 . 而不是做:

    from matplotlib.pyplot import *
    fig = figure() # implicitly create axis
    ax  = gca()
    

    做:

    fig, ax = subplots() # explicitly create figure and axis
    

    类似于绘制这种变化

    draw()
    show()
    fig.canvas.draw()
    fig.show()
    

    通过这种方式,您明确地持有一个特定的数字,而不是依赖于matplotlib当前关注的数字 . ion 命令对我来说有点神秘,因为我的后端始终是交互式的(qt5 / qt4),因此无论如何更新数字属性总是会改变它 .

  • 1

    也许以下是您正在寻找的 . 既然问题非常广泛,同时要求很多东西,我会将其限制在前两个例子中 . 这里的关键是使用 plt.ion() .

    import matplotlib
    matplotlib.use("Qt5Agg")
    import matplotlib.pyplot as plt
    
    
    X=[0,1]
    Y=[0,1]
    Y2a=[0,2]
    Y2b=[0,2.5]
    Y3a=[0,3]
    Y3b=[0,3.5]
    Y4=[0,4]
    
    plt.ion()
    
    fig, ax  = plt.subplots() # Nothing happens
    ax.plot(X,Y) # Nothing happens
    plt.draw()
    plt.pause(.1) # New window (1) appears and shows plot of X,Y; execution continues directly
    ax.set_xlabel('X') # Window 1 gets X axis label
    ax.set_ylabel('Y') # Window 1 gets Y axis label
    figManager = plt.get_current_fig_manager()
    figManager.window.showMinimized() # Window 1 disappears
    plt.pause(10) # No open windows for 10 seconds 
    figManager.window.showNormal() # Window 1 reappears and looks the same as before
    
    
    fig2 = plt.figure() # Nothing happens
    fig2.show() # New window (2) appears and is empty
    ax2 = fig2.gca() # Window 2 shows axes
    ax2.plot(X,Y2a) # Window 2 shows X,Y2a
    pass # Nothing happens, could be omitted
    for i in range(60*2):
        plt.pause(1/2) # Long computation. In the meantime, windows 1 and 2 can still be resized and their controls (zoom etc.) can be used
    ax2.plot(X,Y2b) # Window 2 shows X,Y2a as well as X,Y2b
    figManager = plt.get_current_fig_manager()
    figManager.window.showMinimized() # Window 2 disappears
    

相关问题