bokeh icon indicating copy to clipboard operation
bokeh copied to clipboard

[BUG] vbar_stack is only updated once by CustomJS

Open mosc9575 opened this issue 2 years ago • 0 comments

Software versions

Python version : 3.9.10 | packaged by conda-forge | (main, Feb 1 2022, 21:24:11) IPython version : 8.4.0 Tornado version : 6.1 Bokeh version : 2.4.3 BokehJS static path : /opt/conda/envs/aiva-env/lib/python3.9/site-packages/bokeh/server/static node.js version : v17.4.0 npm version : 8.3.1 Operating system : Linux-4.19.0-20-amd64-x86_64-with-glibc2.31

Browser name and version

Google Chrome Version 104.0.5112.80

Jupyter notebook / Jupyter Lab version

Selected Jupyter core packages... IPython : 8.4.0 ipykernel : 6.9.1 ipywidgets : 7.7.1 jupyter_client : 7.1.2 jupyter_core : 4.9.2 jupyter_server : not installed jupyterlab : not installed nbclient : 0.5.12 nbconvert : 6.4.2 nbformat : 5.1.3 notebook : 6.4.8 qtconsole : not installed traitlets : 5.1.1

Expected behavior

I have a CustomJS block and a Slider and I expect, that the figure is updated every time the slider is moved.

Observed behavior

As you can see in the gif below, the slider is moved but the figure is only updated once.

vstack

To make sure the Source is updated, I printed the updated values to the console, which works fine.

Example code

from bokeh.plotting import figure, show, output_notebook
from bokeh.models import CustomJS,ColumnDataSource, Slider
from bokeh.layouts import column
from bokeh.palettes import GnBu3, OrRd3
output_notebook()

years = ['2015', '2016', '2017']
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
exports = {'fruits' : fruits,
           '2015'   : [2, 1, 4, 3, 2, 4],
           '2015_org'   : [2, 1, 4, 3, 2, 4],
           '2016'   : [5, 3, 4, 2, 4, 6],
           '2017'   : [3, 2, 4, 4, 5, 3]
          }

source = ColumnDataSource(exports)

p = figure(x_range=fruits, plot_height=250, y_range=(0, 16), title="Fruit import/export, by year")

p.vbar_stack(years, x='fruits', width=0.9, color=GnBu3, source=source)

p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None

slider = Slider(start=0, end=5, value=0, step=1, title="2015 exports")

callback = CustomJS(
    args=dict(source=source, slider=slider),
    code="""
    console.log(slider.value)
    let y = source.data['2015'];
    let y_org = source.data['2015_org']
    for (let i = 0; i < y.length; i++) {
        y[i] = y_org[i] + slider.value
    }
    console.log(y)
    source.change.emit();
""")

slider.js_on_change('value', callback)

show(column(p,slider))

Stack traceback or browser console output

None, which is odd.

Comment

Replacing the JavaScript code to

callback = CustomJS(
    args=dict(source=source, slider=slider),
    code="""
    source.data = {
        ...source.data,
        '2015': source.data['2015_org'].map((c) => c + slider.value),
    };
""")

gives the wanted results. But the other version should workd and was working in other examples for me.

mosc9575 avatar Aug 08 '22 15:08 mosc9575