我正在生成一个使用标签的散景报告,有时我可以获得很多这些,并且导航文档变得非常麻烦。幸运的是,这些图有一些属性,可用于将一些图组合在一起。所以我试图实现一种基于这些属性过滤可见选项卡数量的方法。我在使用散景服务器草绘解决方案方面非常成功,但我的最终解决方案需要实现 CustomJS 回调,因为我需要分发 html 报告。我有点迷茫,因为我不熟悉如何实现 CustomJS 回调,或者即使我想要实现的目标在没有散景服务器的情况下也是可能的。我试图根据其他人的帖子来实现一个 CustomJS,但到目前为止我还没有成功。
我的主要目标是用 CustomJS 回调替换“change_plot”回调,如果有人知道这怎么可能,我将不胜感激。
我在下面提供了我的脚本的一个最小示例。任何帮助或指示将不胜感激。
我想要实现的散景服务器版本:
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Tabs, Panel, Dropdown, PreText
from bokeh.plotting import figure, curdoc
#Initialize variables
nplots = 6 # Number of plots
ngroup = 4 # Number of plots assigned to first group
# Definition of report structure
groups = [f'Quad' if i < ngroup else f'Linear' for i in range(nplots)] # Arbitrary grouping of plots
tabnames = [f'Title_{i}' for i in range(nplots)] # Individual plot names
# Creates list of unique groups without modifying first appearance order
cnt = 0
unq_grp = []
original_groups = groups[:]
while len(groups):
cnt = cnt + 1
unq_grp.append(groups[0])
groups = list(filter(lambda group: group != groups[0], groups))
if cnt > len(groups):
break
# Data Variables
x = [None]*nplots
y = [None]*nplots
# Plot Variables
fig = [None]*nplots
source = [None]*nplots
# Generates figures with plots from data with custom process
for i in range(nplots):
x[i] = [x[i] for x[i] in range(0, 10)]
if i < ngroup:
y[i] = [(i*n)**2 for n in x[i]]
else:
y[i] = [(i*n) for n in x[i]]
source[i] = ColumnDataSource(data=dict(x=x[i], y=y[i]))
fig[i] = figure()
fig[i].line('x', 'y', source=source[i], line_width=3, line_alpha=0.6)
# Callback to change Plot and Plot Title
def change_plot(attr, old, new):
index = int(new.split(',')[0])
group = int(new.split(',')[1])
title[group].text = f'Plot: {subgroup[group][index][0]}'
col[group].children[2] = fig[index]
subgroup = [None]*len(unq_grp) #List of tuples ('plot_name', ['tabname_index','unique_group_index'])
menu = [None]*len(unq_grp) #List that populates dropdown menu
group_dd = [None]*len(unq_grp) #Placeholder for dropdown GUI elements
tab = [None]*len(unq_grp) #Placeholder for tab GUI elements
title = [None]*len(unq_grp) #Placeholder for title GUI elements
col = [None]*len(unq_grp) #Placeholder for column GUI elements
# Cycle through each unique group
for i, group in enumerate(unq_grp):
# Filter the figures correspondig to current group
subgroup[i] = [(tabnames[j],str(f'{j},{i}')) if original_group == group else None for j, original_group in enumerate(original_groups)]
# Populates the dropdown menu
menu[i] = list(filter(None,subgroup[i]))
# Reference default figure index (first in the menu)
default = int(menu[i][0][1].split(',')[0])
# Creates GUI/Report elements
group_dd[i] = Dropdown(label = "Select Group", button_type = "default", menu=menu[i])
title[i] = PreText(text=f'Plot: {menu[i][0][0]}', width=200)
col[i] = column([group_dd[i],title[i],fig[default]])
# Listens to callback event
group_dd[i].on_change('value', change_plot)
# Creates tabs
tab[i] = Panel(child = col[i], title = group)
out_tabs = Tabs(tabs = tab)
curdoc().title = "Plotting Tool"
curdoc().add_root(out_tabs)
独立报告(我的代码到目前为止......)
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Tabs, Panel, Dropdown, PreText, CustomJS
from bokeh.plotting import figure, output_file, show
#Initialize variables
nplots = 6 # Number of plots
ngroup = 4 # Number of plots assigned to first group
# Definition of report structure
groups = [f'Quad' if i < ngroup else f'Linear' for i in range(nplots)] # Arbitrary grouping of plots
tabnames = [f'Title_{i}' for i in range(nplots)] # Individual plot names
output_file("tabs.html")
# Creates list of unique groups without modifying first appearance order
cnt = 0
unq_grp = []
original_groups = groups[:]
while len(groups):
cnt = cnt + 1
unq_grp.append(groups[0])
groups = list(filter(lambda group: group != groups[0], groups))
if cnt > len(groups):
break
# Data Variables
x = [None]*nplots
y = [None]*nplots
# Plot Variables
fig = [None]*nplots
source = [None]*nplots
# Generates figures with plots from data with custom process
for i in range(nplots):
x[i] = [x[i] for x[i] in range(0, 10)]
if i < ngroup:
y[i] = [(i*n)**2 for n in x[i]]
else:
y[i] = [(i*n) for n in x[i]]
source[i] = ColumnDataSource(data=dict(x=x[i], y=y[i]))
fig[i] = figure()
fig[i].line('x', 'y', source=source[i], line_width=3, line_alpha=0.6)
figcol = column(fig)
output_file("tabs.html")
subgroup = [None]*len(unq_grp) #List of tuples ('plot_name', ['tabname_index','unique_group_index'])
menu = [None]*len(unq_grp) #List that populates dropdown menu
group_dd = [None]*len(unq_grp) #Placeholder for dropdown GUI elements
tab = [None]*len(unq_grp) #Placeholder for tab GUI elements
title = [None]*len(unq_grp) #Placeholder for title GUI elements
col = [None]*len(unq_grp) #Placeholder for column GUI elements
cjs = [None]*len(unq_grp) #Placeholder for column GUI elements
# Cycle through each unique group
for i, group in enumerate(unq_grp):
# Filter the figures correspondig to current group
subgroup[i] = [(tabnames[j],str(f'{j},{i}')) if original_group == group else None for j, original_group in enumerate(original_groups)]
# Populates the dropdown menu
menu[i] = list(filter(None,subgroup[i]))
# Reference default figure index (first in the menu)
default = int(menu[i][0][1].split(',')[0])
# Creates GUI/Report elements
group_dd[i] = Dropdown(label = "Select Group", button_type = "default", menu=menu[i])
col[i] = column([group_dd[i],fig[default]])
cjs[i] = CustomJS(args=dict(col=col[i], select=group_dd[i], allfigs=figcol), code="""
// Split the index
var dd_val = (select.value)
var valARR = dd_val.split(',')
var index = parseInt(valARR[0])
// replace with appropiate figure?
col.children[1] = allfigs.children[index]
// send new column, maybe?
col.change.emit();
""")
# Listens to callback event
group_dd[i].js_on_change('value',cjs[i])
# Creates tabs
tab[i] = Panel(child = col[i], title = group)
out_tabs = Tabs(tabs = tab)
show(out_tabs)