Skip to content
This repository has been archived by the owner on Mar 20, 2022. It is now read-only.

CustomJS callback for select widgets to update bokeh scatter plot with streamlit_bokeh_events #6

Open
vinayreddy0911 opened this issue Aug 4, 2021 · 0 comments

Comments

@vinayreddy0911
Copy link

Hi, I am new to bokeh applications with streamlit. I am trying to use customJS callback to update my plot if there is any change in the select widgets. I made up the following code and unfortunately plot is not updating after the change in select value.
here is the minimal working example code:

import pandas as pd
import streamlit as st
from copy import deepcopy
import numpy as np
from state import provide_state
import bokeh
from streamlit_bokeh_events import streamlit_bokeh_events
from bokeh.layouts import column, row
from bokeh.models import Slider, TextInput,Dropdown,Select,Button
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, CDSView, annotations, BooleanFilter, CustomJS, HoverTool
from colorcet import glasbey

def get_sizer(X, min_size, max_size):
    X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
    X_scaled = X_std * (max_size - min_size) + min_size
    return X_scaled.fillna(min_size)

my_data = {  'group_1':['cat','dog','cat','dog','bull','bull','cat','rat'],
'group_2':['lion','tiger','deer','tiger','deer','deer','lion','lion'],
'group_3':['grass','bush','flower','leaf','grass','leaf','bush','grass'],
'length':[5,6,5,6,4,3,7,3],
'length_1':[25,36,45,36,54,43,76,37],
'width':[1,2,4,3,4,2,4,5],
'width_1':[11,12,14,13,14,12,14,15],
'size_1': [10,23,45,12,10,45,43,29]
}

st.set_page_config(
    layout="wide",
    page_title="Reference Search",
)
st.write('''# Animal category search''')
st.session_state.data = my_data.copy()
plot_data = pd.DataFrame(st.session_state.data )

coloring = Select(title="Select for coloring:", value="group_1", options=['group_1','group_2','group_3'])
color_label = coloring.value
sizing = Select(title="Select for sizing:", value="size_1", options=['length','length_1','width','width_1','size_1'])
sizing_label = sizing.value

palette = glasbey[:len(plot_data[color_label].unique())]
color_map = bokeh.models.CategoricalColorMapper(factors=plot_data[color_label].unique(),palette=palette)
plot_data['Size'] = get_sizer(plot_data[sizing_label], 10, 40)
plot_data['Half_Size'] = plot_data['Size']/1000

source = ColumnDataSource(plot_data.reset_index().rename(columns={'index':'Animal'}))
print(source.data)
p = figure( plot_width=800, plot_height=600,
    title = 'animal categories',
    tools='''pan,lasso_select,box_select,wheel_zoom,reset''',
    active_scroll = 'wheel_zoom',active_inspect = None,
    toolbar_location = 'above'
)
p.add_layout(annotations.Legend(), 'right')
p.legend.click_policy = 'hide'

p.scatter(x='length',y='width',
          color={'field': color_label, 'transform': color_map},
          legend=color_label, source=source)

callback = CustomJS(args=dict(source=source,plot=p,coloring=coloring,sizing=sizing), code="""
    var data = source.data
    var a =coloring.value;
    var s = sizing.value;
    var palette = glasbey[:len(data[a].unique())];
    var color_map = bokeh.models.CategoricalColorMapper(factors=data[a].unique(),palette=palette)
    plot.color={'field': color_cat_label, 'transform': color_map}
    plot.legend=color_cat_label
    plot.change.emit()
    """)
coloring.js_on_change('value', callback)
sizing.js_on_change('value', callback)

streamlit_bokeh_events(
    events="SelectEvent",
    bokeh_plot=column(row(coloring,sizing,width=800),p),
    key="foo2",
     #refresh_on_update=True,
    debounce_time=0,
)

It is able to produce a scatter plot with colourmap based on grouping initially, but not updating the plot once the grouping parameters for colourmap has changed through a select widget. initially let’s only concentrate on colouring widget, I am working on functionality to update my plot besed on select widgets colour group categories.
To be precise, I am not able to write proper CustomJS callback to update my plot.
when we only stick to coring widget change, there is no change in the source data x and y values. so, please do help me in writing proper CustomJS callback.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant