2017-09-11 27 views
0

私は、特定の属性に基づいて一連のプロダクトを表示するプロットを作成しています。私は、Bokehの「映画」の例からグラフのデザインをモデル化しました。ソースフォルダに移動して"bokeh serve --show shafts" from Andaconda Promptを実行して、私のプロットを実行できます。Bokehデータベースのプロットと更新

私の問題は、付随するデータベースなしで複数の人にHTMLファイルを配布できるように、HTMLファイルを保存する必要があるということです。私は映画の例や私のコードのいずれかからHTMLファイル

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

を保存し、スライダーは、グラフを更新しないHTMLファイルからプロットを実行しようとします。問題は、ファイルを"bokeh serve --show shafts" from Andaconda Promptから実行するとサーバー上で実行されており、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サーバーから実行するためには、どの変数を更新する必要がありますか?

ベローが私のコードです。 for control in controls: control.on_change('value'.......は、サーバー上でグラフを更新するコードの部分ですが、HTMLとして保存すると更新されるように、JavaScriptコードで置換する必要があります。

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にしようとしています。

+0

bokehサーバーを使用する必要がありますか、またはJavaScriptコールバックだけで行うことはできますか? – Anthonydouc

+0

@Anthonydouc私は最終的にjavascriptコールバックを使用して実行しています。 2つの辞書をコールバックに渡す方法を理解する必要がありました.1つは元のデータセットでは静的で、もう1つは選択した基準に基づいて変更しました。私はブラウザコンソールに出力を印刷するのに多くの時間を費やしました。 –

+0

Okは正しいアプローチのように見えますが、頻繁にbokehを使用すると、時間が無駄になることはありません。私は頻繁に別のデータソースの元のデータをプロットなどに使用されているものに維持してきました。 – Anthonydouc

答えて

1

私が望む結果を得るために、私はjavascriptコールバックを通して2つのデータセットを渡しました。決して変更されない元のデータと、最終的にプロットを更新する選択された基準に基づいて修正された元のデータのコピー。

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; 



""") 
関連する問題