Change ColumnDataSource of wedge glyph using Select-JSCallback

I am unable to change ColumnDataSource using select.callback . The Column Names remain the same for all column data sources. Kindly let me know what I am doing wrong here.

This runs on the latest bokeh version 1.3.6

from math import pi

import pandas as pd

from bokeh.io import output_file, show,output_notebook
from bokeh.palettes import Category20c
from bokeh.plotting import figure
from bokeh.models import CustomJS, ColumnDataSource, Slider, Select
from bokeh.layouts import column
from bokeh.transform import cumsum
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource,HoverTool,LinearInterpolator
output_notebook()
#STATE
y = {
    'TamilNadu': 157,
    'AP': 93,
    'Mizoram': 89,
    'Telangana': 63,
    'Maharastra': 44,
    'Karnataka': 42
}
state = pd.Series(y).reset_index(name='value').rename(columns={'index':'territory'})
state['angle'] = state['value']/state['value'].sum() * 2*pi
state['color'] = Category20c[len(y)]
state_cds = ColumnDataSource(state)

#COUNTRY 
x = {
    'United States': 157,
    'United Kingdom': 93,
    'Japan': 98,
    'China': 127,
    'Germany': 144,
    'India': 90
}

country = pd.Series(x).reset_index(name='value').rename(columns={'index':'territory'})
country['angle'] = country['value']/country['value'].sum() * 2*pi
country['color'] = Category20c[len(x)]
country_cds = ColumnDataSource(country)

#name source for piechart(WEDGE)
source = state_cds

#####PLOTTING

pie_chart = figure(plot_height=350, title="Pie Chart", toolbar_location=None, x_range=(-0.5, 1.0))
pie_chart.wedge(x=0, y=1, radius=0.4,
        start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),
        line_color="white", fill_color='color', source=source)
pie_chart.axis.axis_label=None
pie_chart.axis.visible=False
pie_chart.grid.grid_line_color = None


select = Select(options=['state', 'country'],value='state')
select.callback = CustomJS(args={"cds2": state_cds, "cds3": country_cds, "ls": pie_chart,"source" : source}, code="""
         if(cb_obj.value === "state"){ 
                 ls.wedge.source.data = cds2.data
                 }

         }else if(cb_obj.value === "country"){
                  ls.wedge.source.data = cds3.data
        }
         }
         ls.change.emit();
         """)
layout = column(select, pie_chart)
show(layout)

Technically this should produce a callback. I have tried the same thing with p.line and it works. Am I missing out on some java scripting or is my naming convention wrong?

Please help! I am trying to understand how callbacks work.

If you update this to be an actually complete script (i.e. no missing imports, no changes needed to run) then I will run it and take a look.

Hi I have updated the missing import and changes. Please check.

There were a number of issues:

  • Your JavaScript had syntax error (extra un-matched curly braces).
  • You should be updating source since that is the data source that is actually configured on the glyph.
  • You can’t use the same source source = state_cds because as soon as the first callback triggers, you overwrite the state data source with the country data. After that point it is impossible to ever set the original state data because you have erased it. You have to maintain a separate source just for the glyph that you can update from the other two (which do not get modified).
  • Don’t use the old .callback it is deprecated and will be removed in two releaase. Use the generic .js_on_change that works for any property.

Here is a working version:

source = ColumnDataSource(state)

# (plotting code here)

select = Select(options=['state', 'country'], value='state')

callback = CustomJS(args={"cds2": state_cds, "cds3": country_cds, "source": source}, code="""
    if (cb_obj.value == "state") {
        source.data = cds2.data
    } else if(cb_obj.value == "country") {
        source.data = cds3.data
    }
    console.log(source.data)
""")
select.js_on_change('value', callback)
1 Like

Thank you! This helped me a lot!!!