끄적끄적 코딩
article thumbnail
Published 2020. 10. 5. 14:44
[bokeh] 위젯 (Widgets) bokeh
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource, Slider

x = [x*0.005 for x in range(0, 201)]
source = ColumnDataSource(data=dict(x=x, y=x))

plot = figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6,)

slider = Slider(start=0.1, end=8, value=1, step=.1, title="power")

update_curve = CustomJS(args=dict(source=source, slider=slider), code="""
  var data = source.data;
  var f = slider.value;
  var x = data['x'];
  var y = data['y'];
  for (var i = 0; i < x.length; i++) {
    y[i] = Math.pow(x[i], f)
  }

  source.change.emit();
""")
slider.js_on_change('value', update_curve)

show(column(slider, plot))

CustomJS를 통해 js code를 작성합니다.
위의 예제에서는 slider를 연결하여
변경된 값의 결과값을 확인할 수 있습니다.

 

from bokeh.layouts import column, row
from bokeh.models import CustomJS, Slider
from bokeh.plotting import ColumnDataSource, figure, show

x = np.linspace(0, 10, 500)
y = np.sin(x)
source = ColumnDataSource(data=dict(x=x, y=y))

plot = figure(y_range=(-10, 10), plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

amp_slider = Slider(start=0.1, end=10, value=1, step=.1, title="Amplitude")
freq_slider = Slider(start=0.1, end=10, value=1, step=.1, title="Frequency")
phase_slider = Slider(start=0, end=6.4, value=0, step=.1, title="Phase")
offset_slider = Slider(start=-5, end=5, value=0, step=.1, title="Offset")

callback = CustomJS(args=dict(source=source, 
                              amp=amp_slider, freq=freq_slider,
                              phase=phase_slider, offset=offset_slider),
                    code="""
                      const data = source.data;
                      const A = amp.value;
                      const k = freq.value;
                      const phi = phase.value;
                      const B = offset.value;
                      const x = data['x']
                      const y = data['y']
                      for (var i = 0; i < x.length; i++) {
                        y[i] = B + A * Math.sin(k * x[i] + phi);
                      }
                      source.change.emit()
                    """)

amp_slider.js_on_change('value', callback)
freq_slider.js_on_change('value', callback)
phase_slider.js_on_change('value', callback)
offset_slider.js_on_change('value', callback)

layout = row(
    plot,
    column(amp_slider, freq_slider, phase_slider, offset_slider),
)

show(layout)

CustomJS에서 4가지 slider을 연결해서 해당 값의 변경될 때 결과를 확인할 수 있습니다.

 

from random import random

x = [random() for x in range(200)]
y = [random() for y in range(200)]
color = ["blue"] * len(x)

s1 = ColumnDataSource(data=dict(x=x, y=y, color=color))
p = figure(plot_width=400, plot_height=400, tools="lasso_select")
p.circle('x', 'y', color='color', size=8, alpha=0.4, source=s1,
         selection_color="orange", selection_alpha=0.4)

s2 = ColumnDataSource(data=dict(xm=[0, 1], ym=[0.5, 0.5]))
p.line(x='xm', y='ym', color='red', line_width=5, alpha=0.6, source=s2)

callback = CustomJS(args=dict(s1=s1, s2=s2), code="""
  var inds = s1.selected.indices;
  if (inds.length === 0)
    return;

  var ym = 0;
  for (var i = 0; i < inds.length; i++) {
    ym += s1.data.y[inds[i]];
  }

  ym /= inds.length;
  s2.data.ym = [ym, ym];
  s2.change.emit();
""")

s1.selected.js_on_change('indices', callback)

show(p)

선택된 영역에서 중앙위치로 빨간색 선이 이동합니다

검색 태그