用于Matplotlib交互的IPython Notebook小部件

use*_*916 10 python matplotlib ipython ipython-notebook

我想使用ipython笔记本小部件为内联matplotlib图添加一定程度的交互性.

一般情况下,情节可能很重,我只想更新情节的特定元素.我知道小部件内置一个限制功能,有助于不会泛滥内核,但是当情节需要说30秒时,我不想等待这么长时间来更新一行.

通过阅读示例笔记本,我能够创建一个基本示例,其中我将一个十字光标(由2个滑块驱动)添加到mpl轴.

问题是图形显示两次.这是代码(单元格1):

fig, ax = plt.subplots() 
ax.plot([3,1,2,4,0,5,3,2,0,2,4])
Run Code Online (Sandbox Code Playgroud)

...数字显示...,单元格2(编辑:感谢Thomas K的改进):

vline = ax.axvline(1)
hline = ax.axhline(0.5)

def set_cursor(x, y):
    vline.set_xdata((x, x))
    hline.set_ydata((y, y))
    display(fig)
Run Code Online (Sandbox Code Playgroud)

最后(单元格3):

interact(set_cursor, x=(1, 9, 0.01), y=(0, 5, 0.01))
Run Code Online (Sandbox Code Playgroud)

再次显示小部件的图形.

所以问题是:

  1. 如何禁止第一个数字显示?
  2. 这是正确的方法,还是有更好的方法?

编辑

我发现了一个ipython配置旋钮,根据这款笔记本,可以禁止数字显示

%config InlineBackend.close_figures = False
Run Code Online (Sandbox Code Playgroud)

虽然示例笔记本工作,但我无法弄清楚如何单独使用此选项(没有链接示例中提供的上下文管理器类)来隐藏图形显示.

编辑2

我发现了一些文件的的InlineBackend.close_figures配置.

编辑3

由@shadanan回答引发,我想澄清一下我的目的是将光标添加到现有图形,而不是在每个光标移动时从头开始重绘图.合并单个单元格中的3个单元格:

fig, ax = plt.subplots()
ax.plot([3,1,2,4,0,5,3,2,0,2,4])

vline = ax.axvline(1)
hline = ax.axhline(0.5)

def set_cursor(x, y):
    vline.set_xdata((x, x))
    hline.set_ydata((y, y))
    display(fig)

interact(set_cursor, x=(1, 9, 0.01), y=(0, 5, 0.01))
Run Code Online (Sandbox Code Playgroud)

它"应该"有效,但事实并非如此.第一次执行单元格时,它显示了2个数字.小部件交互后,仅显示1个数字.这是一种"奇怪的行为",需要像@shadanan回答中所示的解决方法.ipython开发者可以对此发表评论吗?这是一个错误吗?

use*_*916 5

解决方案结果非常简单.为了避免显示第一个数字,我们只需要在close()调用之前添加一个interact调用.

回想一下这个问题的例子,像这样的单元格将正确显示一个交互式图形(而不是两个):

fig, ax = plt.subplots()
ax.plot([3,1,2,4,0,5,3,2,0,2,4])
plt.close(fig)

vline = ax.axvline(1)
hline = ax.axhline(0.5)

def set_cursor(x, y):
    vline.set_xdata((x, x))
    hline.set_ydata((y, y))
    display(fig)

interact(set_cursor, x=(1, 9, 0.01), y=(0, 5, 0.01))
Run Code Online (Sandbox Code Playgroud)

更简洁的方法是定义函数add_cursor(在单独的单元格或脚本中):

def add_cursor(fig, ax):
    plt.close(fig)

    vline = ax.axvline(1, color='k')
    hline = ax.axhline(0.5, color='k')

    def set_cursor(x, y):
        vline.set_xdata((x, x))
        hline.set_ydata((y, y))
        display(fig)

    interact(set_cursor, x=ax.get_xlim(), y=ax.get_ylim())
Run Code Online (Sandbox Code Playgroud)

然后每当我们想要添加交互式游标时调用它:

fig, ax = plt.subplots()
ax.plot([3,1,2,4,0,5,3,2,0,2,4])
add_cursor(fig, ax)
Run Code Online (Sandbox Code Playgroud)