ipython笔记本widg中的交互式绘图布局

2024-10-03 17:17:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个图,我想与ipython笔记本小部件进行交互。下面的代码是我所要做的事情的一个简化示例。在

import matplotlib.pyplot as plt
import IPython.html.widgets as wdg

def displayPlot1(rngMax = 10):
    plt.figure(0)
    plt.plot([x for x in range(0, rngMax)])

wdg1 = wdg.interactive(displayPlot1, rngMax = wdg.IntSlider(20))

def displayPlot2(rngMax = 10):
    plt.figure(1)
    plt.plot([x**2 for x in range(0, rngMax)])

wdg2 = wdg.interactive(displayPlot2, rngMax = wdg.IntSlider(10))

wdg.ContainerWidget([wdg.HTML("""<h1>First Plot</h1>"""),
                     wdg1, 
                     wdg.HTML("""<h1>Second Plot</h1>"""), 
                     wdg2])

第一个问题是它首先显示所有的小部件,最后一个接一个地绘制两个图:

^{pr2}$

我想要:

title1
widget1
plot1    
title2
widget2
plot2

而且似乎只要我触摸任何一个滑块,整个输出就会被覆盖,并且只显示一个绘图(我正在更改的那个)。在

我如何解决这个问题?(如果我把它们分成两个不同的单元,我就有可能做到这一点,但是我计划做一些更复杂的事情,最终需要在一个单元中)


Tags: inimportforplot部件defasrange
1条回答
网友
1楼 · 发布于 2024-10-03 17:17:38

IPython笔记本在任何输出之前显示小部件。您可以做的一件事是将绘图放在HTML widget中。它可以放置在相对于其他小部件的任何位置。在

但是,如果这样做,则需要显式地将绘图放在HTML小部件中。这可能有点棘手,但一个快速的解决方案是将绘图的字节字符串保存到缓冲区,然后将字节字符串放入图像标记中。在

下面是一个示例(Gist here):

import base64
import io
import matplotlib.pyplot as plt
import ipywidgets as widgets
from IPython.display import display

def handle_input1(slope):
    plt.figure()
    plt.plot([x * slope for x in range(0, 11)])
    plt.ylim((0,10))
    output1HTML.value = plot_to_html()
    plt.close()

def handle_input2(curvature):
    plt.figure()
    plt.plot([x * x * curvature for x in range(0, 11)])
    plt.ylim((0,100))
    output2HTML.value = plot_to_html()
    plt.close()

def plot_to_html():
    # write image data to a string buffer and get the PNG image bytes
    buf = io.BytesIO()
    plt.savefig(buf, format='png')
    buf.seek(0)
    return """<img src='data:image/png;base64,{}'/>""".format(base64.b64encode(buf.getvalue()).decode('ascii'))

plt.ioff()

heading1HTML = widgets.HTML("""<h1>Slope</h1>""")
input1Float = widgets.FloatSlider(value=0.5, min=0.0, max=1.0, step=0.01, description="slope: ")
widgets.interactive(handle_input1, slope=input1Float)
output1HTML = widgets.HTML()

heading2HTML = widgets.HTML("""<h1>Curvature</h1>""")
input2Float = widgets.FloatSlider(value=0.5, min=0.0, max=1.0, step=0.01, description="curvature: ")
widgets.interactive(handle_input2, curvature=input2Float)
output2HTML = widgets.HTML()

display(widgets.Box([heading1HTML, input1Float, output1HTML, heading2HTML, input2Float, output2HTML]))

handle_input1(input1Float.value)
handle_input2(input2Float.value)

编辑1:IPython小部件已移至IPython.html;相应地更新了代码。在

编辑2:使用widgets.interactive根据最新的IPython widgets documentation;再次更新IPython小部件位置;添加ASCII编码

相关问题 更多 >