2017-08-02 13 views
1

私は、垂直IntSliderの位置をmatplotlibの右側に変更する方法を検討しています。ここでは、コードは次のようになります。ipywidgetスライダのデフォルト位置をmatplotlib figureの側に変更する方法は?

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

に非常に単純な方法があるかもしれませんこれを行うが、私は自分自身を把握することはできません。

私はIPython.displayVBoxを包む、その後VBoxfiginteractiveウィジェットの両方を配置しようとしましたが、それはうまくいきませんでした。

この例では、これに対するストレートな解決策が見つかりませんでした。

EDIT1:

ipywidgets出力領域を捕捉し、ウィジェット・コンテキスト内で使用Output()クラスを提供します。

私はそれを使い方を理解しようとします。

これはオブジェクトです: https://github.com/jupyter-widgets/ipywidgets/blob/master/ipywidgets/widgets/widget_output.py

+0

私の解決策を以下に試しましたか? –

+1

はい、あなたは正しい道にいると思います。 update_plot関数からFigureとAxesの構築をアンラップして動作させる方法を見つけたら、私はあなたに答えます。 Output()オブジェクトを多く使用します。私はこれが私たちの問題を解決すると思います。 –

答えて

1

あなたはインタラクティブなウィジェットを作成し、HBoxchildrenをロードすることでこの問題を解決することができます。インタラクティブの子ウィジェットはこの規約に従います。 (widget_0、widget_1 ...、output)タプルの最後のメンバーはコントロールウィジェットの出力です。 HBoxのレイアウトは、宣言する前または後で定義できます。 Read more on the layouts available here

次の解決方法にはいくつかの注意点があります。最初にグラフが表示されないことがあります。コントロールが表示される前に微調整しなければならない場合があります.2番目に%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])) 
+1

問題を部分的に解決しましたが、matplotlib図の構成をupdate_plot関数内にラップすると、この不適切なリフレッシュ動作が発生し、スライダを最初に更新したときに図が作成されます。 matplotlibを使って出力をキャプチャする方法があります。 これを確認してください: https://github.com/jupyter-widgets/ipywidgets/blob/master/ipywidgets/widgets/widget_output.py –

+0

@BrunoRuasDePinhoフリッカーはあなたのブラウザやバージョンと関係があります[この問題](https://github.com/jupyter-widgets/ipywidgets/issues/1532)に記載されているように使用しているipywidgetsの数'%matplotlib notebook'の代わりに'%matplotlib inline'を使ってわずかな改善が見られるかもしれませんが、いくつかの対話的機能を使用しています。だからIDKはこれが今のところうまくいくかもしれません。私は探しているが、少なくとも部分的なsolnのためのupvoteを投げる: –

+1

確かにジェームス!ありがとう!! –

2

私は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関数にラップする必要はありません。

bqplotドキュメントから:bqplotで

、プロットのすべての単一の属性は、インタラクティブ ウィジェットです。これにより、ユーザーは任意のプロットをIPython ウィジェットと統合して、簡単なPythonコード行 から複雑で機能豊富なGUIを作成することができます。

元の質問に回答したので、私は受け入れられたジェームスの答えを保持します。

関連する問題