javascript - Bokeh 数据库绘图和更新

标签 javascript python bokeh

我正在创建一个图,该图将根据产品的特定属性显示一系列产品。我根据 Bokeh 的“电影”示例对图表的设计进行了建模。我可以通过导航到源文件夹并从 Andaconda Prompt 执行“bokehserve --showshafts”来运行我的绘图

我的问题是我需要保存一个 HTML 文件,以便我可以将其分发给多个人,而无需附带数据库。如果我尝试保存 HTML 文件

"output_file("slider.html", title="slider.py example")"

无论是电影示例还是我的代码,然后从 HTML 文件运行绘图, slider 都不会更新图表。我认为问题在于,当您从 Andaconda Prompt 中的“bokehserve --show axiss”运行文件时,它正在服务器上运行,并且能够连续访问 python 代码。

或者,当您从 HTML 运行它时,它会将所有代码编译为 JASON 格式,并且无法再访问 python 代码。为了解决这个 Bokeh 添加了小的 Javascript 部分,这些部分将继续在服务器上更新。

Bokeh 给出了如何执行此操作的多个示例,但我没有完全掌握 Javascript 中正在更新的内容来更新图表。我对 JS 不是很熟悉,所以有点困难。他们给出的一个简单的例子是:

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

output_file("callback.html")
x = [j*0.005 for j 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;
        var f = cb_obj.value
        x = data['x']
        y = data['y']
        for (i = 0; i < x.length; i++) {
            y[i] = Math.pow(x[i], f)
        }
        source.change.emit();
    """)

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

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

y[i] 显然是为了更新绘图而更新的内容,但我无法弄清楚它与原始 python 更新有何关系,或者为什么此更改会影响似乎的图表超出其范围。我真正的问题是在我的代码中,我需要更新哪些变量才能使代码在 Bokeh 服务器上运行。

波纹管是我的代码。控件中的控件的 : control.on_change('value'....... 是在服务器上更新图形的代码部分,但我需要将其替换为 JavaScript代码,以便在保存为 HTML 时它会更新。

callback = CustomJS(args=dict(source=source), code="""
var data = source.data;
selected = shafts[
    ((data.Weight2g >= min_weight_slider.value) &&
    (data.Weight2g <= max_weight_slider.value) &&
    (data.Butt_Frequency >= min_butt_freq_slider.value) &&
    (data.Butt_Frequency <= max_butt_freq_slider.value) &&
    (data.Tip_Frequency >= min_tip_freq_slider.value) &&
    (data.Tip_Frequency <= max_tip_freq_slider.value) &&
    (data.Torque >= min_torque_slider.value) &&
    (data.Torque <= max_torque_slider.value))
];
data = selected;
source.data = selected;
}
source.change.emit;
""")

min_weight_slider = Slider(title="Minimum Weight", value=40,

    start=40.0, end=200.0, step=0.5, callback = callback)
callback.args["min_weight_slider"] = min_weight_slider

max_weight_slider = Slider(title="Maximum Weight", value=200, start=40.0, end=200.0, step=0.5, callback = callback)
callback.args["max_weight_slider"] = max_weight_slider

min_butt_freq_slider = Slider(title="Minimum Butt Frequency", value=180.0, start=100.0, end=500.0, step=10.0, callback = callback)
callback.args["min_butt_freq_slider"] = min_butt_freq_slider

max_butt_freq_slider = Slider(title="Maximum Butt Frequency", value=500.0, start=100.0, end=500.0, step=10.0, callback = callback)
callback.args["max_butt_freq_slider"] = max_butt_freq_slider

min_tip_freq_slider = Slider(title="Minimum Tip Frequency", value=180, start=100, end=500, step=10, callback = callback)
callback.args["min_tip_freq_slider"] = min_tip_freq_slider

max_tip_freq_slider = Slider(title="Maximum Tip Frequency", value=400, start=100, end=500, step=10, callback = callback)
callback.args["max_tip_freq_slider"] = max_tip_freq_slider

min_torque_slider = Slider(title="Minimum Torque", value=2, start=1, end=20, step=0.1, callback = callback)
callback.args["min_torque_slider"] = min_torque_slider

max_torque_slider = Slider(title="Maximum Torque", value=15, start=1, end=20, step=0.1, callback = callback)
callback.args["max_torque_slider"] = max_torque_slider

x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="Butt_Frequency")
callback.args["x_axis"] = x_axis
y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()), value="Tip_Frequency")
callback.args["y_axis"] = y_axis


def select_shafts():
selected = shafts[
    (shafts.Weight2g >= min_weight_slider.value) &
    (shafts.Weight2g <= max_weight_slider.value) &
    (shafts.Butt_Frequency >= min_butt_freq_slider.value) &
    (shafts.Butt_Frequency <= max_butt_freq_slider.value) &
    (shafts.Tip_Frequency >= min_tip_freq_slider.value) &
    (shafts.Tip_Frequency <= max_tip_freq_slider.value) &
    (shafts.Torque >= min_torque_slider.value) &
    (shafts.Torque <= max_torque_slider.value) 
]
return selected      



#updates the 
def update():
df = select_shafts()

        #re-names the above function
x_name = axis_map[x_axis.value]
y_name = axis_map[y_axis.value]

p.xaxis.axis_label = x_axis.value
p.yaxis.axis_label = y_axis.value
p.title.text = "%d shafts selected" % len(df)
source.data = dict(
    x=df[x_name],
    y=df[y_name],
    color=df["color"],
    Manufacture=df["Manufacture"],
    Model = df["Model"],
    Type = df["Type"],
    Weight = df["Weight"],
    Flex=df["Flex"],
    Butt_Frequency = df["Butt_Frequency"],
    Tip_Frequency = df["Tip_Frequency"],
    Torque=df["Torque"],
    Weight2G = df["Weight2g"],
    Availability = df["Availability"],
    alpha=df["alpha"]
)








controls = [min_weight_slider, max_weight_slider,   min_butt_freq_slider, max_butt_freq_slider, min_tip_freq_slider, max_tip_freq_slider, min_torque_slider, max_torque_slider,x_axis, y_axis]


#for control in controls:
#control.on_change('value', lambda attr, old, new: update())

sizing_mode = 'fixed'  # 'scale_width' also looks nice with this   example


inputs = widgetbox(*controls, sizing_mode=sizing_mode)
    #Widget box produced with bokeh

l = layout([
[inputs, p]
], sizing_mode=sizing_mode)

update()  # initial load of the data

curdoc().add_root(l)
curdoc().title = "Shafts"

show(l)

提前非常感谢

我想添加有关我解决问题的尝试的更新。我意识到,当程序在 Bokeh 服务器上运行时,它能够不断更新绘图函数可以访问的源数据。当程序运行 JS 函数时,它只能更新单个字典条目键内的值。

我正在尝试modify这个代码来模拟我的需要。

最佳答案

为了获得我想要的结果,我通过 JavaScript 回调传递了两个数据集。从未修改的原始数据,然后根据选定的标准修改原始数据的副本,最终更新绘图。

callback = CustomJS(args={"orgData": originalData, "modData": sourceData}, code="""

var oData = orgData.data;
var updateData = modData.data;



var holdData = {'x':[],'y':[],'color':[], 'Manufacture':[],'Model':[],'Type':[],
'Weight':[],'Flex':[],'Butt_Frequency':[],'Tip_Frequency':[],
'Torque':[],'WeightMes':[],'Availability':[],'alpha':[]};

console.log(Manufacture_Select.value.includes(oData.Manufacture[1])); 
//console.log(min_weight_slider.value);
//console.log((oData.WeightMes[1] >= min_weight_slider.value) && (oData.WeightMes[1] <= max_weight_slider.value));

var xAxisSelection = String(x_axis.value);
var yAxisSelection = String(y_axis.value);
var avalButSelNames = [];

for (i = 0; i < avalibility_Button.active.length; i++){

    avalButSelNames.push(avalibility_Button.labels[avalibility_Button.active[i]]);

}
console.log(avalButSelNames)
for(i = 0; i < oData.Manufacture.length; i++){
       if((oData.WeightMes[i] >= weight_slider.value[0])&& 
            (oData.WeightMes[i] <= weight_slider.value[1]) &&
            (oData.Butt_Frequency[i] >= butt_freq_slider.value[0]) &&
            (oData.Butt_Frequency[i] <= butt_freq_slider.value[1]) &&
            (oData.Tip_Frequency[i] >= tip_freq_slider.value[0]) &&
            (oData.Tip_Frequency[i] <= tip_freq_slider.value[1]) &&
            (oData.Torque[i] >= torque_slider.value[0]) &&
            (oData.Torque[i] <= torque_slider.value[1]) &&
            (oData.Balance_Point[i] <= Balance_Point_Slider.value[1]) &&
            (oData.Balance_Point[i] >= Balance_Point_Slider.value[0]) &&
            (Manufacture_Select.value.includes(oData.Manufacture[i])) &&
            (Type_Select.value.includes(oData.Type[i]))&&
            (Flex_Select.value.includes(oData.Flex[i]))&&
            (avalButSelNames.includes(oData.Availability[i]))

       ){
           holdData['x'].push(oData[xAxisSelection][i]);
           holdData['y'].push(oData[yAxisSelection][i]);
           holdData['color'].push(oData.color[i]);
           holdData['Manufacture'].push(oData.Manufacture[i]);
           holdData['Model'].push(oData.Model[i]);
           holdData['Type'].push(oData.Type[i]);
           holdData['Weight'].push(oData.Weight[i]);
           holdData['Flex'].push(oData.Flex[i]);
           holdData['Butt_Frequency'].push(oData.Butt_Frequency[i]);
           holdData['Tip_Frequency'].push(oData.Tip_Frequency[i]);
           holdData['Torque'].push(oData.Torque[i]);
           holdData['WeightMes'].push(oData.WeightMes[i]);
           holdData['Availability'].push(oData.Availability[i]);
           holdData['alpha'].push(oData.alpha[i]);
           //console.log(i);
       }
    }




modData.data = holdData;

labels = plot.get('renderers');
labels[0]["attributes"]["axis_label"] = xAxisSelection;
labels[2]["attributes"]["axis_label"] = yAxisSelection;



""")

关于javascript - Bokeh 数据库绘图和更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46164727/

相关文章:

python - py3k : case-insensitive list sorting - With or WIthout lambda?

javascript - 导航栏错误

javascript - 使用 WebAudio 合并/混合两个音频流

python - 对于简单的 ERP 系统,我可以选择哪种 Python Web 框架?

python - 通用迭代器注释 Python

python - 如何用 Bokeh 生成气泡图

python Bokeh 直方图: adjusting x scale and chart style

python - 根据列名为 NetworkX 节点分配颜色

javascript - window.open() 在 chrome 中打开一个空白屏幕

javascript - 带按键暂停的 setTimeout 函数