Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Bokeh support #202

Open
theeldermillenial opened this issue Jul 9, 2023 · 4 comments
Open

Feature Request: Bokeh support #202

theeldermillenial opened this issue Jul 9, 2023 · 4 comments

Comments

@theeldermillenial
Copy link

Just wanted to request Bokeh integration. I realize it can be somewhat supported with the display functionality, but having integration would be nice to get analogous functionality to Altair and Plotly.

https://bokeh.org/

@maartenbreddels
Copy link
Contributor

Bokeh rendering/loading is a bit odd, because there are two parts

  1. injecting the bokehjs library in the notebook using output_notebook()/display()
  2. rendering the bokeh plot, which expects 1 to have happened in the past, (i.e. the window.Bokeh object is expected to be available in the frontend).

In solara, 1 and 2 happen really fast, and the Bokeh object is not available yet.

However, if we poll for this, we can make this work:

from typing import Callable

import numpy as np
from bokeh.io import output_notebook
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from jupyter_bokeh import BokehModel

import solara

rng = np.random.default_rng()


@solara.component_vue('bokeh_loaded.vue')
def BokehLoaded(loaded: bool, on_loaded: Callable[[bool], None]):
    pass

def PlotBokeh(fig: figure):
    loaded = solara.use_reactive(False)
    with solara.Column():
        output_notebook(hide_banner=True)
        BokehLoaded(loaded=loaded.value, on_loaded=loaded.set)
        if loaded.value:
            BokehModel.element(model=fig)




@solara.component
def Page():
    data = {"x_values": [1, 2, 3, 4, 5], "y_values": rng.random(5)}
    source = ColumnDataSource(data=data)
    p = figure(title="Simple line example", x_axis_label="x", y_axis_label="y")
    p.line(x="x_values", y="y_values", source=source, legend_label="Temp.", line_width=2)

    def on_click():
        print("new data")
        data = {"x_values": [1, 2, 3, 4, 5], "y_values": rng.random(5)}
        source.data = data

    with solara.Card("Bokeh"):
        solara.Button(label="Click me", on_click=on_click)
        PlotBokeh(p)

bokeh_loaded.vue:

<template>
    <div v-if="!loaded">Loading bokeh...</div>
</template>
<script>
module.exports = {
    mounted() {
        const check = () => {
            if (window.Bokeh) {
                this.loaded = true;
                return;
            }
            setTimeout(check, 100);
        }
        check();
    }
}
</script>

cc @Jhsmit who is also interested in this.

cc @philippjfr if the above is correct, I wouldn't be surprised if sometimes the rendering in notebook, lab or voila fails because step 1 takes too long.

@theeldermillenial
Copy link
Author

theeldermillenial commented Jul 13, 2023

This looks like the solution I have been working towards. Almost exactly. It's taking me a bit because I don't know Vue. Your sample code will help me with my solution. I'm happy to share/contribute.

Your Vue template looks more succinct than mine because I was trying to update the Bokeh plot using the Vue template.

@theeldermillenial
Copy link
Author

Actually, I created a component that has a time delayed loading function. I created a Solara component to interact with Cardano wallets, and the Cardano wallet extensions in the browser take awhile to load. So I have a delay and repeat tries kind of like what you have here.

@maartenbreddels
Copy link
Contributor

@Jhsmit you might be interested in this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants