2017-10-30 10 views
1

bokeh 시각화 작업 중 하나는 클라이언트 측에서 대화 형 기능을 구현하기 위해 CustomJS을 사용하여 서버없이 실행된다는 것입니다. 자바 스크립트를 사용하여. ColumnDataSourceCustomJS으로 전달하면 대화 형으로 플롯을 업데이트하는 데 문제가 없습니다.`CustomJS`를 사용하여 파이썬에서 bokeh로 임의의`json` 데이터를 전달하는 방법

그러나 내가 할 수없는 것은 출력 HTML에 임의의 json 데이터를 포함시키는 것입니다.

내 경우
from bokeh.io import output_file 
from bokeh.layouts import widgetbox 
from bokeh.models import CustomJS 
from bokeh.models.widgets import Div, Button 
from bokeh.plotting import show 

data_for_client = { 
    "x": 3, 
    "y": { 
     "foo": [1, 2, 3], 
     "bar": {"some_bar": "doge", "other bar": "much json"} 
    }, 
    "z": [[1, 2], [3, 4]] 
} 

callback = CustomJS(args={"data_for_client": data_for_client}, code=""" 
    console.log(data_for_client); 
""") 

content = widgetbox(
    Button(label="click here", callback=callback), 
    Div(text="some complicated interactive stuff based on json content here") 
) 

output_file("issue.html") 
show(content) 

data_for_clientjsonjson, 다른 부분은 일부 위젯과 사용자의 상호 작용에 따라 사용되는 중첩 복잡해은 다음과 같습니다 아래의 자체 포함 된 예를 참조하십시오.

사용자 상호 작용을 기준으로 json 데이터를 수정할 필요가 없으며 모든 청취자 나 특별한 것을 첨부 할 수 있습니다. CustomJS 콜백에서 사용할 수있는 json 값의 콘텐츠가 필요합니다.

그러나 나는 일반 json 데이터에 대한 유사한 아무것도 찾을 수없는, 단순한 열 데이터의 경우, 나는 ColumnDataSource 내 데이터를 포장 할 수 있으며 CustomJS에 대한 인수로 그 전달합니다. 위의 코드는 메시지와 함께 실패합니다

ValueError: expected an element of Dict(String, Instance(Model)), got {'data_for_client': {'x': 3, 'y': {'foo': [1, 2, 3], 'bar': {'some_bar': 'doge', 'other bar': 'much json'}}, 'z': [[1, 2], [3, 4]]}} 

답변

1

그렇지 않으면 당신은 사전 키가 같은 사전 ({...}를) 사용할 수 없기 때문에 당신은 관련 라인에서 "data_for_client"에 처음 data_for_client을 변경해야

from bokeh.io import output_file 
from bokeh.layouts import widgetbox 
from bokeh.models import CustomJS 
from bokeh.models.widgets import Div, Button 
from bokeh.plotting import show 

data_for_client = { 
    "x": 3, 
    "y": { 
     "foo": [1, 2, 3], 
     "bar": {"some_bar": "doge", "other bar": "much json"} 
    }, 
    "z": [[1, 2], [3, 4]] 
} 

# Here is the change: 
callback = CustomJS(args={"data_for_client": data_for_client}, code=""" 
    console.log(data_for_client); 
""") 

content = widgetbox(
    Button(label="click here", callback=callback), 
    Div(text="some complicated interactive stuff based on json content here") 
) 

output_file("issue.html") 
show(content) 
+0

좋아, 내 얼굴의 얼굴. 그러나 이것은 문제를 해결하지 못한다. 나는이 점에 관해서 질문을 편집했다. –

+0

Ajax/Json-Datasource와 같은 것이 있다고 가정합니다. – MEE

+0

Ajax 데이터 소스가 존재하며, 웹 서버에서 데이터를 전송하는 것으로 알고 있습니다. 문서에서 json 소스를 찾지 못했습니다. –

1

문자열로 전달할 수 있습니다. json 문자열에서 json 데이터를 읽는 데 javascript가 필요하다고 생각합니다. 적어도이 코드는 Python에 있습니다.

from bokeh.io import show 
from bokeh.layouts import widgetbox 
from bokeh.models import CustomJS, ColumnDataSource 
from bokeh.models.widgets import Div, Button 
import json 

data_for_client = { 
    "x": [3], 
    "y": { 
      "foo": [1, 2, 3], 
      "bar": {"some_bar": "doge", "other bar": "much json"} 
     }, 
    "z": [[1, 2], [3, 4]], 
} 

json_string = json.dumps(data_for_client) 

DumButton = Button(label=json_string) 

# Here is the change: 
callback = CustomJS(args={"db":DumButton}, code=""" 
    console.log(db.label); 
    var test=JSON.parse(db.label); 
    console.log(test); 
    for(key in test){console.log(test[key])} 
    """) 

content = widgetbox(
    Button(label="click here", callback=callback), 
) 

show(content) 
+0

기술적으로는 효과가 있지만 큰 json을 사용하면 이상적이지 않다. json (JSON.parse()'javascript에서)'callback' 호출 될 때마다. 나는'ColumnDataSource'의 단일 셀에서 전체 json을 문자열로 전달하여 비슷한 솔루션을 시도했지만 사용자 상호 작용에 눈에 띄는 지연이있었습니다. –

+0

@SamDeMeyer 작동하는 코드로 내 대답을 편집했습니다. Python 측에서 json.dumps를 사용하고 JS 측에서 json.parseo를 사용합니다. 빨리 할 수있는 방법이 있는지 모르겠습니다. json을 파이썬의 파일에 저장 한 다음 customJS에서 읽는 것이 더 빠릅니까? 나는 중첩 된 dictonaries를 전달하는 내장 bokeh 내장 방법을 모른다. 목록을리스트로 매핑하고 ColumnDataSource를 사용할 수 있습니다. – Seb

+0

문제는'var test = JSON.parse (db.label);'줄에서'JSON.parse'를 호출하는 것입니다. 이것은 '콜백'이 호출 될 때마다 (즉,이 예제에서 '여기를 클릭하십시오'버튼을 누를 때마다) 다시 평가됩니다. 'ColumnDataSource'의 경우 브라우저에서 문서를로드 할 때 데이터가 한 번만 파싱됩니다. 현재 다른 방법이 없다는 것이 맞을 수도 있습니다. 그러나이 기능은 너무 간단해서 그곳에 있어야합니다. –