代码之家  ›  专栏  ›  技术社区  ›  Bruno Ruas De Pinho

如何将ipywidget滑块的默认位置更改为matplotlib图形的侧面?

  •  4
  • Bruno Ruas De Pinho  · 技术社区  · 7 年前

    我正在寻找一种方法来改变matplotlib图右侧垂直IntSlider的位置。下面是代码:

    from ipywidgets import interact, fixed, IntSlider
    import numpy as np
    from matplotlib import pyplot as plt
    
    %matplotlib notebook
    
    fig = plt.figure(figsize=(8,4))
    
    xs = np.random.random_integers(0, 5000, 50)
    ys = np.random.random_integers(0, 5000, 50)
    
    ax = fig.add_subplot(111)
    scat, = ax.plot(xs, ys, 'kx', markersize=1)
    ax.grid(which='both', color='.25', lw=.1)
    ax.set_aspect('equal'), ax.set_title('Rotate')
    
    def rotate(theta, xs, ys):
        new_xs = xs * np.cos(np.deg2rad(theta)) - ys * np.sin(np.deg2rad(theta))
        new_xs -= new_xs.min()
        new_ys = xs * np.sin(np.deg2rad(theta)) + ys * np.cos(np.deg2rad(theta))
        new_ys -= new_ys.min()
        return new_xs, new_ys
    
    def update_plot(theta, xs, ys):
        new_xs, new_ys = rotate(theta, xs, ys)
        scat.set_xdata(new_xs), scat.set_ydata(new_ys)
        ax.set_xlim(new_xs.min() - 500, new_xs.max() + 500)
        ax.set_ylim(new_ys.min() - 500, new_ys.max() + 500)
    
    w = interact(update_plot, 
                 theta=IntSlider(min=-180, max=180, step=5,value=0, orientation='vertical'), 
                 xs=fixed(xs), 
                 ys=fixed(ys))
    

    enter image description here

    这就是我想要的:

    enter image description here

    也许有一个非常简单的方法可以做到这一点,但我自己也不知道。

    fig interactive 将小部件放入 VBox 然后包装 具有 IPython.display

    无法在示例中找到此问题的直接解决方案。

    编辑1:

    ipywidgets提供了一个 Output() 类,该类捕获输出区域并在小部件上下文中使用它。

    我会设法弄清楚如何使用它。

    这是目标: https://github.com/jupyter-widgets/ipywidgets/blob/master/ipywidgets/widgets/widget_output.py

    2 回复  |  直到 7 年前
        1
  •  4
  •   Bruno Ruas De Pinho    7 年前

    bqplot 而不是matplotlib,结果更简单。

    import numpy as np
    from bqplot import pyplot as plt
    from IPython.display import display
    from ipywidgets import interactive, fixed, IntSlider, HBox, Layout
    
    plt.figure(min_aspect_ratio=1, max_aspect_ratio=1)
    
    xs = np.random.randint(0, 5000 + 1, 100)
    ys = np.random.randint(0, 5000 + 1, 100)
    
    scat = plt.scatter(xs, ys)
    
    def rotate(theta, xs, ys):
        new_xs = xs * np.cos(np.deg2rad(theta)) - ys * np.sin(np.deg2rad(theta))
        new_xs -= new_xs.min()
        new_ys = xs * np.sin(np.deg2rad(theta)) + ys * np.cos(np.deg2rad(theta))
        new_ys -= new_ys.min()
        return new_xs, new_ys
    
    def update_plot(theta, xs, ys):
        new_xs, new_ys = rotate(theta, xs, ys)
        scat.x, scat.y = new_xs, new_ys
    
    w = interactive(update_plot, 
                 theta=IntSlider(min=-180, max=180, step=5,value=0, orientation='vertical'), 
                 xs=fixed(xs), 
                 ys=fixed(ys))
    
    box_layout = Layout(display='flex', flex_flow='row', justify_content='center', align_items='center')
    display(HBox([plt.current_figure(), w], layout=box_layout))
    

    bqplot update_plot

    BQ图 文档:

    在bqplot中,plot的每一个属性都是一个交互属性 小部件,只需从几个小部件中创建一个复杂且功能丰富的GUI Python代码的简单行。

    我将保留公认的James答案,因为它回答了原始问题。

        2
  •  3
  •   James Draper dineep thomas    7 年前

    children 变成一个 HBox .交互式的子窗口小部件遵循此约定;(小部件0,小部件1…,输出),其中元组的最后一个成员是控制小部件的输出。您可以在声明之前或之后定义HBox的布局。 Read more on the layouts available here .

    以下解决方案有几个注意事项;图形最初可能不会显示,您可能需要在控件出现之前对其进行调整,然后使用 %matplotlib notebook

    from IPython.display import display
    from ipywidgets import interactive, fixed, IntSlider, HBox, Layout
    import numpy as np
    import matplotlib.pylab as plt
    %matplotlib notebook
    
    def rotate(theta, xs, ys):
        new_xs = xs * np.cos(np.deg2rad(theta)) - ys * np.sin(np.deg2rad(theta))
        new_xs -= new_xs.min()
        new_ys = xs * np.sin(np.deg2rad(theta)) + ys * np.cos(np.deg2rad(theta))
        new_ys -= new_ys.min()
        return new_xs, new_ys
    
    def update_plot(theta, xs, ys):
        fig = plt.figure(figsize=(8,4))
        ax = fig.add_subplot(111)
        scat, = ax.plot(xs, ys, 'kx', markersize=1)
        ax.grid(which='both', color='.25', lw=.1)
        ax.set_aspect('equal'), ax.set_title('Rotate')
        new_xs, new_ys = rotate(theta, xs, ys)
        scat.set_xdata(new_xs), scat.set_ydata(new_ys)
        ax.set_xlim(new_xs.min() - 500, new_xs.max() + 500)
        ax.set_ylim(new_ys.min() - 500, new_ys.max() + 500)
    
    xs = np.random.randint(0, 5000, 50)
    ys = np.random.randint(0, 5000, 50)
    w = interactive(update_plot,
                    theta=IntSlider(min=-180, max=180, step=5, value=0,orientation='vertical'), 
                    xs=fixed(xs),
                    ys=fixed(ys))
    
    # Define the layout here.
    box_layout = Layout(display='flex', flex_flow='row', justify_content='space-between', align_items='center')
    
    display(HBox([w.children[1],w.children[0]], layout=box_layout))
    

    更新:

    ipywidgets gitter .

    from IPython.display import display, clear_output
    from ipywidgets import interact, fixed, IntSlider, HBox, Layout, Output, VBox
    import numpy as np 
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    def rotate(theta, xs, ys):
        new_xs = xs * np.cos(np.deg2rad(theta)) - ys * np.sin(np.deg2rad(theta))
        new_xs -= new_xs.min()
        new_ys = xs * np.sin(np.deg2rad(theta)) + ys * np.cos(np.deg2rad(theta))
        new_ys -= new_ys.min()
        return new_xs, new_ys
    
    out = Output(layout={'width': '300px', 'height': '300px'})
    
    def update_plot(change): 
        theta = change['new'] # new slider value 
        with out: 
            clear_output(wait=True)
            fig = plt.figure(figsize=(4,4))
            ax = fig.add_subplot(111)
            scat, = ax.plot(xs, ys, 'kx', markersize=1)
            ax.grid(which='both', color='.25', lw=.1)
            ax.set_aspect('equal'), ax.set_title('Rotate')
            new_xs, new_ys = rotate(theta, xs, ys) 
            scat.set_xdata(new_xs), scat.set_ydata(new_ys)
            ax.set_xlim(new_xs.min() - 500, new_xs.max() + 500)
            ax.set_ylim(new_ys.min() - 500, new_ys.max() + 500)
            plt.show()
    
    xs = np.random.randint(0, 5000, 50) 
    ys = np.random.randint(0, 5000, 50) 
    
    slider = IntSlider(min=-180, max=180, step=5, value=0, orientation='vertical') 
    slider.observe(update_plot, 'value')
    update_plot({'new': slider.value}) 
    display(HBox([out, slider]))