散景中点击工具的 JS 回调
JS callback for tap tools in bokeh
我想做一个交互式图表。在第一个图中,使用“点击”小部件,选择“悬停”小部件显示的值“x”,在第二个图上绘制值 d(:,x)。当您再次单击“点击”小部件到图 1 中的另一个位置时,图 2 会更新。但我不知道如何为“点击”小部件编写回调。
我正在寻找的一个例子是这个
提供的代码创建了两个图,但不更新第二个图:
import numpy as np
from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.plotting import figure, show
from bokeh.layouts import row
import os
from numpy.lib.function_base import select
import pandas as pd
from bokeh.models import ColumnDataSource, CustomJS, TapTool
N = 500
x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = np.sin(xx)*np.cos(yy)
len_d=len(d)
plot1 = figure(tooltips=[("x", "$x{0}"), ("y", "$y"), ("value", "@image")],
plot_height=350, plot_width=400,title="Graph 1 d",tools = "tap")
plot2=figure(plot_height=350, plot_width=400, title="Graph 2 d(tap selection(x))",
tools="pan,box_select,crosshair,box_zoom,reset,save,wheel_zoom,hover")
#f = d[:,select]
lines = plot2.line(x = 'x', y = 'y', source = ColumnDataSource({'x': d[0] , 'y': -np.arange(len_d)}))
lines.visible = False
plot1.x_range.range_padding = plot1.y_range.range_padding = 0
data = dict(
image=[d], pattern=['smooth ramp'],
x=[0], y=[5], dw=[20], dh=[10]
)
code = '''if (cb_data.source.selected.indices.length > 0){
lines.visible = true;
var selected_index = cb_data.source.selected.indices[0];
lines.data_source.data['x'] = d[selected_index]
lines.data_source.change.emit();
}'''
cds = ColumnDataSource(data=data)
plot1.image(source=cds, x=0, y=-len(d), dw=len(d[0]), dh=len(d),palette='Spectral11', level="image")
plot1.grid.grid_line_width = 0.5
plot1.select(TapTool).callback = CustomJS(args = {'lines': lines, 'd': d}, code = code)
plots = row(plot1, plot2)
show(plots)
非常感谢您提供的任何帮助
这是一个从图像中选择数据的解决方案。
import numpy as np
import pandas as pd
from bokeh.plotting import figure, output_notebook, show
from bokeh.layouts import row
from bokeh.models import ColumnDataSource, CustomJS
output_notebook()
N = 500
x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = np.sin(xx)*np.cos(yy)
len_d=len(d)
data = dict(
image=[d], pattern=['smooth ramp'],
x=[0], y=[5], dw=[20], dh=[10]
)
# plot 1
cds_p1 = ColumnDataSource(data=data)
plot1 = figure(
plot_height=350,
plot_width=400,
title="Graph 1 d",
x_range =(0,500),
y_range =(-500, 0),
tooltips=[("x", "$x{0}")]
)
plot1.grid.grid_line_width = 0.5
plot1.image(
source=cds_p1,
x=0,
y=-len_d,
dw=len_d,
dh=len_d,
palette='Spectral11',
level="image"
)
# plot 2
y_index = -np.arange(len_d)
cds_p2 = ColumnDataSource(
{'x': d[0] , 'y':-np.arange(len_d) }
)
plot2=figure(
plot_height=350,
plot_width=400,
title="Graph 2 d(tap selection(x))",
x_range =(-1,1),
y_range =(-500, 0),
tools="")
plot2.line(x = 'x', y = 'y', source=cds_p2)
# important JS part
callback = CustomJS(
args=dict(cds_original=cds_p1, cds_p2=cds_p2),
code="""
// console.log('Tap event occurred at x-position: ' + cb_obj.x)
const data = cds_original.data
const next = cds_p2.data
var xpos = Math.round(cb_obj.x)
console.log((xpos-1)*500)
console.log(data['image'])
var x = []
for(var i=xpos; i<500*500; i+=500){
console.log(data['image'][0][i])
x.push(data['image'][0][i])
}
next['x'] = x
console.log(next)
cds_p2.change.emit()
""")
plot1.js_on_event('tap', callback)
plots = row(plot1, plot2)
show(plots)
我认为这不是最终的解决方案,但也许这会让您更近一步。
我想做一个交互式图表。在第一个图中,使用“点击”小部件,选择“悬停”小部件显示的值“x”,在第二个图上绘制值 d(:,x)。当您再次单击“点击”小部件到图 1 中的另一个位置时,图 2 会更新。但我不知道如何为“点击”小部件编写回调。 我正在寻找的一个例子是这个
提供的代码创建了两个图,但不更新第二个图:
import numpy as np
from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.plotting import figure, show
from bokeh.layouts import row
import os
from numpy.lib.function_base import select
import pandas as pd
from bokeh.models import ColumnDataSource, CustomJS, TapTool
N = 500
x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = np.sin(xx)*np.cos(yy)
len_d=len(d)
plot1 = figure(tooltips=[("x", "$x{0}"), ("y", "$y"), ("value", "@image")],
plot_height=350, plot_width=400,title="Graph 1 d",tools = "tap")
plot2=figure(plot_height=350, plot_width=400, title="Graph 2 d(tap selection(x))",
tools="pan,box_select,crosshair,box_zoom,reset,save,wheel_zoom,hover")
#f = d[:,select]
lines = plot2.line(x = 'x', y = 'y', source = ColumnDataSource({'x': d[0] , 'y': -np.arange(len_d)}))
lines.visible = False
plot1.x_range.range_padding = plot1.y_range.range_padding = 0
data = dict(
image=[d], pattern=['smooth ramp'],
x=[0], y=[5], dw=[20], dh=[10]
)
code = '''if (cb_data.source.selected.indices.length > 0){
lines.visible = true;
var selected_index = cb_data.source.selected.indices[0];
lines.data_source.data['x'] = d[selected_index]
lines.data_source.change.emit();
}'''
cds = ColumnDataSource(data=data)
plot1.image(source=cds, x=0, y=-len(d), dw=len(d[0]), dh=len(d),palette='Spectral11', level="image")
plot1.grid.grid_line_width = 0.5
plot1.select(TapTool).callback = CustomJS(args = {'lines': lines, 'd': d}, code = code)
plots = row(plot1, plot2)
show(plots)
非常感谢您提供的任何帮助
这是一个从图像中选择数据的解决方案。
import numpy as np
import pandas as pd
from bokeh.plotting import figure, output_notebook, show
from bokeh.layouts import row
from bokeh.models import ColumnDataSource, CustomJS
output_notebook()
N = 500
x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = np.sin(xx)*np.cos(yy)
len_d=len(d)
data = dict(
image=[d], pattern=['smooth ramp'],
x=[0], y=[5], dw=[20], dh=[10]
)
# plot 1
cds_p1 = ColumnDataSource(data=data)
plot1 = figure(
plot_height=350,
plot_width=400,
title="Graph 1 d",
x_range =(0,500),
y_range =(-500, 0),
tooltips=[("x", "$x{0}")]
)
plot1.grid.grid_line_width = 0.5
plot1.image(
source=cds_p1,
x=0,
y=-len_d,
dw=len_d,
dh=len_d,
palette='Spectral11',
level="image"
)
# plot 2
y_index = -np.arange(len_d)
cds_p2 = ColumnDataSource(
{'x': d[0] , 'y':-np.arange(len_d) }
)
plot2=figure(
plot_height=350,
plot_width=400,
title="Graph 2 d(tap selection(x))",
x_range =(-1,1),
y_range =(-500, 0),
tools="")
plot2.line(x = 'x', y = 'y', source=cds_p2)
# important JS part
callback = CustomJS(
args=dict(cds_original=cds_p1, cds_p2=cds_p2),
code="""
// console.log('Tap event occurred at x-position: ' + cb_obj.x)
const data = cds_original.data
const next = cds_p2.data
var xpos = Math.round(cb_obj.x)
console.log((xpos-1)*500)
console.log(data['image'])
var x = []
for(var i=xpos; i<500*500; i+=500){
console.log(data['image'][0][i])
x.push(data['image'][0][i])
}
next['x'] = x
console.log(next)
cds_p2.change.emit()
""")
plot1.js_on_event('tap', callback)
plots = row(plot1, plot2)
show(plots)
我认为这不是最终的解决方案,但也许这会让您更近一步。