Streamlit bokeh event for graph interactions

Hi all,

I am trying to make interact two scatterplots and an histogram chart using bokeh.

I think I have to use a single ColumnDataSource to enable interactions between my two scatter plots. Then I would have retrieved the data from the selections made through either one or the other scatter plot to feed an histogram chart using streamlit_bokeh_events.

The ColumnDataSource contains columns x, y and yres and the expected plots are the following:

  • Scatter plot 1 : y=f(x)

  • Scatter plot 2 : yres=f(x)

  • Histogram : distribution of yres

Trying to do so I am facing problems with ColumnDataSource sharing in streamlit:

RuntimeError: Models must be owned by only a single document, Selection(id='7644', ...) is already in a doc

My sample code:

import streamlit as st
import pandas as pd
import random

from bokeh.models import ColumnDataSource, CustomJS
from bokeh.plotting import figure
from streamlit_bokeh_events import streamlit_bokeh_events

st.set_page_config(layout="wide")

@st.cache()
def get_y(x):
    return [i*i*i*(1 + random.randint(-100,100)/1000) for i in x]
x = range(1,100,1)
y = get_y(x)
yref = [i*i*i for i in x]

df = pd.DataFrame(dict(x=x, y=y))
df['yest'] = yref
df['yres'] = df['y'] - df['yest']
df.reset_index()

# create plot
cds = ColumnDataSource(df)

# define events
cds.selected.js_on_change(
    "indices",
    CustomJS(
        args=dict(source=cds),
        code="""
        document.dispatchEvent(
            new CustomEvent("INDEX_SELECT", {detail: {data: source.selected.indices}})
        )
        """
    )
)
tools = 'box_select,reset'

def xy(x,y):
    xy = figure(tools=tools)
    xy.circle(x=x, y=y, source=cds)
    r = streamlit_bokeh_events(
        bokeh_plot=xy,
        events="INDEX_SELECT",
        key=x+y,
        refresh_on_update=True,
        debounce_time=0
    )
    _indices = []
    if r:
        if r.get("INDEX_SELECT"):
            _indices.extend(r.get("INDEX_SELECT")["data"])

xy('x','y')
xy('x','yres')

Any help would be appreciated.

Thanks