Passing generated plot in python to javascript

Hello, I have a Bokeh plot created in Python/ Streamlit and embedded in a React application. I want to improve performance by keeping the zoom level on the client side so that Streamlit does not refresh. To achieve this, I plan to partially generate the plot in Python and then pass it down to JavaScript. After that, I want to add the zoom levels in JavaScript before embedding the plot.

    plot = generate_plot()
      
    # Apply zoom-level 
    plot.x_range = Range1d(….) # skip line 1
    plot.y_range = Range1d(….) # skip line 2

    div_id = "".join(choices(ascii_letters, k=16)) # skip line 3
    fig_dict = json_item(plot, div_id) # skip line 4
    json_figure = json.dumps(fig_dict) # skip line 5
	
    # json_figure is sent to javascript to be embedded using the example in the bokeh documentation for version 2.4.3

What I want to do is to skip the block of code above to be able to send the plot down to the javascript script and apply zoom on the javascript side then generate the json_figure and embed it. The problem is plot is not JSON serializable and plot.to_json() did not work.

Can anyone provide suggestions on how to achieve this?
Alternatively, is there a possibility to apply plot.x_range and plot.y_range on an embedded bokeh plot?
I thought the example here Json_item for javascript is helpful but doesn’t address my issue completely.
Thank you.

You can try this :

# PYTHON #
from bokeh.embed import json_item
import json

chart1_data = json.dumps(json_item(plot))

#JS#
function myFunction() {

                            
                                fetch('/get_chart')
                                .then(res => res.json())
                                .then(data =>  Bokeh.embed.embed_item(data,"yourDivId"))
                           
                            };

1 Like

Thanks for your response, according to the documentation, this approach works only if you running and API server like flask as shown below. Am I missing something?

@app.route('/plot')
def plot():
    p = make_plot('petal_width', 'petal_length')
    return json.dumps(json_item(p, "myplot"))

Yes, you need to fech the chart data/config from your backend.
On the other hand, if you want to handle bokeh directly with JS you should consider the option of passing only the data of the graph from the backend (x,y) and then with that data generate directly the graph with bokehjs, having the control in the JS.

1 Like

Definitely need some additional context here. Bokeh plots are zoomable purely on the JS side by default using standard wheel and box zoom tools, etc., assuming you just want to zoom one set of data. Do you mean that you have multi-resolution data and some other mechanism for specifying “zoom level” (a streamlit… widget? control of some sort? I am not very familiar with streamlit at all) and want to be able to switch between different levels of the data based on that? If so can you just add all the data to one plot up front and selectively turn off and on the visibility of the glyphs for each data set? That seems much simpler, but I am also not sure I understand the situation.

1 Like

Sorry for the late reply. The problem is that after converting/serializing the plot to an embeddable JSON/ Object, I cannot revert it back to the plot again so I cannot set properties like x_range, and y_range.

The Bokeh server will keep the Python <–> JS sides in sync. There are APIs for converting Python Bokeh documents into JSON to be re-constituted as JS objects. There are not currently any official APIs for the reverse (i.e. for converting JSON into Python objects)

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.