2017-09-11 69 views
0

我正在創建一個基於其特定屬性顯示一系列產品的情節。我模擬了Bokeh的「電影」示例中的圖形設計。我可以通過導航到源文件夾並執行"bokeh serve --show shafts" from Andaconda Prompt來運行我的情節。散景數據庫繪圖和更新

我的問題是我需要保存一個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]顯然是什麼正在更新,更新的情節,但我想不出它如何與原有的蟒蛇更新或者爲什麼這種變化可以影響其圖似乎超出了它的範圍。我真正的問題是在我的代碼中,我需要更新哪些變量才能使代碼從Bokeh服務器運行。

貝婁是我的代碼。 for control in controls: 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服務器上運行時,它可以不斷更新plot函數可以訪問的源數據。當程序運行JS函數時,它只能更新單個字典輸入鍵中的值。

我試圖modify這個代碼來嘲笑我的需要。

+0

你需要使用散景服務器,還是你可以做只與JavaScript回調? – Anthonydouc

+0

@Anonydouc我最終得到它使用JavaScript回調運行。我必須弄清楚如何將兩個字典傳遞給回調函數,其中一個與原始數據集保持靜態,另一個基於所選標準進行修改。我花了很多時間將輸出打印到瀏覽器控制檯。 –

+0

好吧看起來像正確的做法,我懷疑如果你經常使用散景,花費的時間將被浪費。我經常將原始數據保存在單獨的數據源中,以便用於繪圖等。 – Anthonydouc

回答

1

爲了得到我想要的結果,我通過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; 



""")