โบเก้ - การเพิ่มวิดเจ็ต

โมดูล bokeh.models.widgets มีคำจำกัดความของวัตถุ GUI ที่คล้ายกับองค์ประกอบในรูปแบบ HTML เช่นปุ่มแถบเลื่อนช่องทำเครื่องหมายปุ่มตัวเลือก ฯลฯ การควบคุมเหล่านี้มีส่วนติดต่อแบบโต้ตอบกับพล็อต การเรียกใช้การประมวลผลเช่นการแก้ไขข้อมูลพล็อตการเปลี่ยนพารามิเตอร์พล็อต ฯลฯ สามารถดำเนินการได้โดยฟังก์ชัน JavaScript แบบกำหนดเองที่ดำเนินการกับเหตุการณ์ที่เกี่ยวข้อง

Bokeh ช่วยให้สามารถกำหนดฟังก์ชันการโทรกลับได้ด้วยสองวิธี -

  • ใช้ CustomJS callback เพื่อให้การโต้ตอบทำงานในเอกสาร HTML แบบสแตนด์อโลน

  • ใช้ Bokeh server และตั้งค่าตัวจัดการเหตุการณ์

ในส่วนนี้เราจะดูวิธีเพิ่มวิดเจ็ต Bokeh และกำหนดการเรียกกลับ JavaScript

ปุ่ม

วิดเจ็ตนี้เป็นปุ่มที่คลิกได้โดยทั่วไปใช้เพื่อเรียกใช้ตัวจัดการการโทรกลับที่ผู้ใช้กำหนด ตัวสร้างใช้พารามิเตอร์ต่อไปนี้ -

Button(label, icon, callback)

พารามิเตอร์ label คือสตริงที่ใช้เป็นคำอธิบายภาพของปุ่มและการเรียกกลับคือฟังก์ชัน JavaScript ที่กำหนดเองที่จะเรียกใช้เมื่อคลิก

ในตัวอย่างต่อไปนี้วิดเจ็ตพล็อตและปุ่มจะแสดงในเค้าโครงคอลัมน์ พล็อตเองแสดงสัญลักษณ์เส้นระหว่างชุดข้อมูล x และ y

ฟังก์ชัน JavaScript ที่กำหนดเองชื่อ 'callback' ถูกกำหนดโดยใช้ CutomJS() function. ได้รับการอ้างอิงถึงออบเจ็กต์ที่ทริกเกอร์การเรียกกลับ (ในกรณีนี้คือปุ่ม) ในตัวแปรรูปแบบ cb_obj

ฟังก์ชันนี้จะเปลี่ยนแปลงข้อมูล ColumnDataSource ต้นทางและสุดท้ายจะส่งการอัปเดตนี้ในข้อมูลต้นทาง

from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import Figure, output_file, show
from bokeh.models.widgets import Button

x = [x*0.05 for x in range(0, 200)]
y = x

source = ColumnDataSource(data=dict(x=x, y=y))
plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

callback = CustomJS(args=dict(source=source), code="""
   var data = source.data;
   x = data['x']
   y = data['y']
   for (i = 0; i < x.length; i++) {
      y[i] = Math.pow(x[i], 4)
   }
   source.change.emit();
""")

btn = Button(label="click here", callback=callback, name="1")

layout = column(btn , plot)
show(layout)

เอาต์พุต (เริ่มต้น)

คลิกที่ปุ่มด้านบนของพล็อตและดูรูปพล็อตที่อัปเดตซึ่งมีลักษณะดังนี้ -

เอาต์พุต (หลังจากคลิก)

ตัวเลื่อน

ด้วยความช่วยเหลือของตัวควบคุมแถบเลื่อนคุณสามารถเลือกหมายเลขระหว่างคุณสมบัติเริ่มต้นและสิ้นสุดที่กำหนดให้

Slider(start, end, step, value)

ในตัวอย่างต่อไปนี้เราลงทะเบียนฟังก์ชันการโทรกลับในเหตุการณ์ on_change ของตัวเลื่อน ค่าตัวเลขทันทีของ Slider พร้อมใช้งานสำหรับตัวจัดการในรูปแบบของ cb_obj.value ซึ่งใช้เพื่อแก้ไขข้อมูล ColumnDatasource รูปพล็อตจะอัปเดตอย่างต่อเนื่องเมื่อคุณเลื่อนตำแหน่ง

from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import Figure, output_file, show
from bokeh.models.widgets import Slider

x = [x*0.05 for x in range(0, 200)]
y = x

source = ColumnDataSource(data=dict(x=x, y=y))
plot = Figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

handler = CustomJS(args=dict(source=source), code="""
   var data = source.data;
   var f = cb_obj.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 = Slider(start=0.0, end=5, value=1, step=.25, title="Slider Value")

slider.js_on_change('value', handler)
layout = column(slider, plot)
show(layout)

เอาต์พุต

RadioGroup

วิดเจ็ตนี้นำเสนอคอลเลกชันของปุ่มสลับที่ใช้ร่วมกันซึ่งแสดงปุ่มวงกลมทางด้านซ้ายของคำอธิบายภาพ

RadioGroup(labels, active)

โดยที่ป้ายกำกับคือรายการคำอธิบายภาพและใช้งานอยู่คือดัชนีของตัวเลือกที่เลือก

เลือก

วิดเจ็ตนี้เป็นรายการแบบเลื่อนลงแบบง่ายของรายการสตริงซึ่งหนึ่งในนั้นสามารถเลือกได้ สตริงที่เลือกจะปรากฏที่หน้าต่างด้านบนและเป็นพารามิเตอร์ค่า

Select(options, value)

รายการองค์ประกอบสตริงในดรอปดาวน์จะได้รับในรูปแบบของอ็อบเจ็กต์รายการตัวเลือก

ต่อไปนี้เป็นตัวอย่างรวมของปุ่มตัวเลือกและวิดเจ็ตที่เลือกซึ่งทั้งสองมีความสัมพันธ์ที่แตกต่างกันสามแบบระหว่างชุดข้อมูล x และ y RadioGroup และ Select widgets ได้รับการลงทะเบียนกับตัวจัดการที่เกี่ยวข้องโดยใช้เมธอด on_change ()

from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.plotting import Figure, output_file, show
from bokeh.models.widgets import RadioGroup, Select

x = [x*0.05 for x in range(0, 200)]
y = x

source = ColumnDataSource(data=dict(x=x, y=y))

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

radiohandler = CustomJS(args=dict(source=source), code="""
   var data = source.data;
   console.log('Tap event occurred at x-position: ' + cb_obj.active);
   //plot.title.text=cb_obj.value;
   x = data['x']
   y = data['y']
   if (cb_obj.active==0){
      for (i = 0; i < x.length; i++) {
         y[i] = x[i];
      }
   }
   if (cb_obj.active==1){
      for (i = 0; i < x.length; i++) {
         y[i] = Math.pow(x[i], 2)
      }
   }
   if (cb_obj.active==2){
      for (i = 0; i < x.length; i++) {
         y[i] = Math.pow(x[i], 4)
      }
   }
   source.change.emit();
""")

selecthandler = CustomJS(args=dict(source=source), code="""
   var data = source.data;
   console.log('Tap event occurred at x-position: ' + cb_obj.value);
   //plot.title.text=cb_obj.value;
   x = data['x']
   y = data['y']
   if (cb_obj.value=="line"){
      for (i = 0; i < x.length; i++) {
         y[i] = x[i];
      }
   }
   if (cb_obj.value=="SquareCurve"){
      for (i = 0; i < x.length; i++) {
         y[i] = Math.pow(x[i], 2)
      }
   }
   if (cb_obj.value=="CubeCurve"){
      for (i = 0; i < x.length; i++) {
         y[i] = Math.pow(x[i], 4)
      }
   }
   source.change.emit();
""")

radio = RadioGroup(
   labels=["line", "SqureCurve", "CubeCurve"], active=0)
radio.js_on_change('active', radiohandler)
select = Select(title="Select:", value='line', options=["line", "SquareCurve", "CubeCurve"])
select.js_on_change('value', selecthandler)

layout = column(radio, select, plot)
show(layout)

เอาต์พุต

วิดเจ็ตแท็บ

เช่นเดียวกับในเบราว์เซอร์แต่ละแท็บสามารถแสดงหน้าเว็บที่แตกต่างกันวิดเจ็ตแท็บคือโมเดลโบเก้ที่ให้มุมมองที่แตกต่างกันสำหรับแต่ละรูป ในตัวอย่างต่อไปนี้พล็อตตัวเลขสองเส้นของเส้นโค้งไซน์และโคไซน์ถูกแสดงผลในสองแท็บที่แตกต่างกัน -

from bokeh.plotting import figure, output_file, show
from bokeh.models import Panel, Tabs
import numpy as np
import math
x=np.arange(0, math.pi*2, 0.05)
fig1=figure(plot_width=300, plot_height=300)

fig1.line(x, np.sin(x),line_width=2, line_color='navy')

tab1 = Panel(child=fig1, title="sine")
fig2=figure(plot_width=300, plot_height=300)
fig2.line(x,np.cos(x), line_width=2, line_color='orange')
tab2 = Panel(child=fig2, title="cos")

tabs = Tabs(tabs=[ tab1, tab2 ])

show(tabs)

เอาต์พุต