Glyphs are not reflecting values update in ColumnDataSource

I am trying to show and hide the circle glyphs using a MultiSelect widget. As you can see from the code below the callback function successfully empties the ColumnDataSource dictionary, but the glyphs are still in the graph.

I have used a Slider widget similarly and I was able to filter glyphs successfully.

If you run the code below and then select and unselect the Liquid option from the MultiSelect list on the webpage you should be able to see in the terminal prints that liquid.data is being updated, but the glyphs (orange circles) on the webpage do not change.

Anyone know the reason?

#Importing libraries
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.sampledata.periodic_table import elements
from bokeh.models import Range1d, PanTool, ResetTool, HoverTool, ColumnDataSource, MultiSelect
from bokeh.layouts import layout

#Remove rows with NaN values and then map standard states to colors
elements.dropna(inplace=True) #if inplace is not set to True the changes are not written to the dataframe
colormap={‘gas’:‘yellow’,‘liquid’:‘orange’,‘solid’:‘red’}
elements[‘color’]=[colormap for x in elements[‘standard state’]]

gas_original=ColumnDataSource(elements[elements[‘standard state’]==‘gas’])
liquid_original=ColumnDataSource(elements[elements[‘standard state’]==‘liquid’])
solid_original=ColumnDataSource(elements[elements[‘standard state’]==‘solid’])

#Create three ColumnDataSources for elements of unique standard states
gas=ColumnDataSource(elements[elements[‘standard state’]==‘gas’])
liquid=ColumnDataSource(elements[elements[‘standard state’]==‘liquid’])
solid=ColumnDataSource(elements[elements[‘standard state’]==‘solid’])

#Create the figure object
f=figure()

#adding glyphs
f.circle(x=“atomic radius”, y=“boiling point”,
size=[i/10 for i in gas.data[“van der Waals radius”]],
fill_alpha=0.2,color=“color”,legend=‘Gas’,source=gas)

f.circle(x=“atomic radius”, y=“boiling point”,
size=[i/10 for i in liquid.data[“van der Waals radius”]],
fill_alpha=0.2,color=“color”,legend=‘Liquid’,source=liquid)

f.circle(x=“atomic radius”, y=“boiling point”,
size=[i/10 for i in solid.data[“van der Waals radius”]],
fill_alpha=0.2,color=“color”,legend=‘Solid’,source=solid)

#Add axis labels
f.xaxis.axis_label=“Atomic radius”
f.yaxis.axis_label=“Boiling point”

def filter_elements(attr,old,new):
liquid.data={key:[value for i, value in enumerate(liquid_original.data[key]) if “liquid” in multiselect.value] for key in liquid_original.data}
print(“multiselect value …”,multiselect.value)
print(“liquid data …”,liquid.data)

#create multiselect widget
options=[(“gas”,“Gas”),(“liquid”,“Liquid”),(“solid”,“Solid”)]
multiselect=MultiSelect(title=“Options”, options=options)
multiselect.on_change(“value”,filter_elements)

#Add Select widget to layout and then the layout to curdoc
lay_out=layout([[multiselect]])
curdoc().add_root(f)
curdoc().add_root(lay_out)

``

Hi Adi,

The problem is that when you are calling .circle you are passing an explicit data source, AND also passing in a list literal (for size). This causes all kinds of problems and has been recently deprecated (you should see a warning with the lates version) and will result in an error in the very near future. If you are passing the "source" argument to a glyph method, then ALL the column data needs to go in that source.

Just FYI the clue to figuring this out quickly was to look at the browsers JS console for messages. In this case it said:

  [bokeh] – "Error handling message: Error: attempted to retrieve property array for nonexistent field 'size', [object MessageEvent]"

Then I immediately noticed that you'd pass size as a list literal.

Thanks,

Bryan

···

On Oct 18, 2016, at 6:47 AM, Adi <[email protected]> wrote:

I am trying to show and hide the circle glyphs using a MultiSelect widget. As you can see from the code below the callback function successfully empties the ColumnDataSource dictionary, but the glyphs are still in the graph.

I have used a Slider widget similarly and I was able to filter glyphs successfully.

If you run the code below and then select and unselect the Liquid option from the MultiSelect list on the webpage you should be able to see in the terminal prints that liquid.data is being updated, but the glyphs (orange circles) on the webpage do not change.

Anyone know the reason?

#Importing libraries
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.sampledata.periodic_table import elements
from bokeh.models import Range1d, PanTool, ResetTool, HoverTool, ColumnDataSource, MultiSelect
from bokeh.layouts import layout

#Remove rows with NaN values and then map standard states to colors
elements.dropna(inplace=True) #if inplace is not set to True the changes are not written to the dataframe
colormap={'gas':'yellow','liquid':'orange','solid':'red'}
elements['color']=[colormap for x in elements['standard state']]

gas_original=ColumnDataSource(elements[elements['standard state']=='gas'])
liquid_original=ColumnDataSource(elements[elements['standard state']=='liquid'])
solid_original=ColumnDataSource(elements[elements['standard state']=='solid'])

#Create three ColumnDataSources for elements of unique standard states
gas=ColumnDataSource(elements[elements['standard state']=='gas'])
liquid=ColumnDataSource(elements[elements['standard state']=='liquid'])
solid=ColumnDataSource(elements[elements['standard state']=='solid'])

#Create the figure object
f=figure()

#adding glyphs
f.circle(x="atomic radius", y="boiling point",
         size=[i/10 for i in gas.data["van der Waals radius"]],
         fill_alpha=0.2,color="color",legend='Gas',source=gas)

f.circle(x="atomic radius", y="boiling point",
         size=[i/10 for i in liquid.data["van der Waals radius"]],
         fill_alpha=0.2,color="color",legend='Liquid',source=liquid)

f.circle(x="atomic radius", y="boiling point",
         size=[i/10 for i in solid.data["van der Waals radius"]],
         fill_alpha=0.2,color="color",legend='Solid',source=solid)

#Add axis labels
f.xaxis.axis_label="Atomic radius"
f.yaxis.axis_label="Boiling point"

def filter_elements(attr,old,new):
    liquid.data={key:[value for i, value in enumerate(liquid_original.data[key]) if "liquid" in multiselect.value] for key in liquid_original.data}
    print("multiselect value ...",multiselect.value)
    print("liquid data ...",liquid.data)

#create multiselect widget
options=[("gas","Gas"),("liquid","Liquid"),("solid","Solid")]
multiselect=MultiSelect(title="Options", options=options)
multiselect.on_change("value",filter_elements)

#Add Select widget to layout and then the layout to curdoc
lay_out=layout([[multiselect]])
curdoc().add_root(f)
curdoc().add_root(lay_out)

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/255860ac-0f74-4bc7-a4d6-19c363a7d178%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.