2017-09-11 2 views
0

특정 속성을 기반으로 다양한 제품을 표시하는 플롯을 작성 중입니다. Bokeh의 "영화"예제에서 그래프의 디자인을 모델링했습니다. 원본 폴더로 이동하여 "bokeh serve --show shafts" from Andaconda Prompt을 실행하여 내 플롯을 실행할 수 있습니다.Bokeh 데이터베이스 플로팅 및 업데이트

내 문제는 첨부 파일없이 여러 사람에게 배포 할 수 있도록 HTML 파일을 저장해야한다는 것입니다. 내가 저장하려고 경우 HTML은 영화 예제 또는 내 코드 중 하나에서

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

를 제출 한 후 HTML에서 플롯 그래프를 업데이트하지 슬라이더를 파일을 실행합니다. 문제는 그 파일을 "bokeh serve --show shafts" from Andaconda Prompt에서 실행할 때 서버에서 실행 중이며 계속해서 파이썬 코드에 액세스 할 수 있다고 생각합니다.

또는 HTML에서 실행하면 모든 코드를 JASON 형식으로 컴파일하고 더 이상 파이썬 코드에 액세스 할 수 없습니다. 이 문제를 해결하기 위해 Bokeh는 서버에서 계속 업데이트 될 작은 자바 스크립트 섹션을 추가했습니다.

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'.......은 서버에서 그래프를 업데이트하는 코드 부분이지만 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 서버를 사용해야합니까, 아니면 자바 스크립트 콜백만으로 할 수 있습니까? – Anthonydouc

+0

@Anthonydouc 궁극적으로 나는 자바 스크립트 콜백을 사용하여 실행하고있다. 두 개의 사전을 콜백에 전달하는 방법을 알아 내야했습니다. 하나는 원래 데이터 세트로 정적이었고 하나는 선택한 기준에 따라 수정 된 것입니다. 나는 출력을 브라우저 콘솔에 출력하는데 많은 시간을 할애했다. –

+0

Ok는 정확한 접근 방법처럼 보이고, 자주 bokeh를 사용하면 낭비되는 시간을 낭비하게됩니다. 필자는 플로팅 등을 위해 사용되는 데이터 소스와는 별도의 데이터 소스에서 원래의 데이터를 자주 유지 보수했습니다. – Anthonydouc

답변

1

원하는 결과를 얻으려면 자바 스크립트 콜백을 통해 두 개의 데이터 세트를 전달해야합니다. 수정되지 않은 원본 데이터와 최종적으로 플롯을 업데이트하는 선택된 기준에 따라 수정 된 원본 데이터의 복사본입니다.

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; 



""") 
관련 문제