0

I followed the guide posted here to create a visualization tool similar to the one from Gapminder (the animated bubble graph) using my own dataset.

Everything worked fine (although I had to change a few lines for the slider JavaScript Callback code from the guide in my own code).

However, I noticed that when the slider is at position 0 or 1, both values will map to the same date in the source object referenced by the callback.

For reference:

  • 0 maps to the date (08/28/2019) whereas 1 maps to the date (08/29/2019).
  • The js_source_array_engagement String object looks like: {0: _0, 1: _1, 2: _2, 3: _3, 4: _4, 5: _5, 6: _6, 7: _7, 8: _8, 9: _9, 10: _10, 11: _11, 12: _12, 13: _13, 14: _14, 15: _15}.
  • The engagement_sources is a dictionary and has the following keys: '_0', '_1', '_2', '_3', '_4', '_5', '_6', '_7', '_8', '_9', '_10', '_11', '_12', '_13', '_14', '_15'. The keys map to ColumnDataSource Objects.
  • As a result, the String object js_source_array_engagement will be used to reference the engagement_sources in the JS callback.

This is the code for the slider:

''' ############ ADD SLIDER ############ '''
code = """
    var day = slider.value,
        sources = %s,
        new_source_data = sources[day].data;

    console.log(day);
    console.log(sources[day].data['days'][0]);

    text = new_source_data['days'][0];
    renderer_source.data = new_source_data;
    text_source.data = {'days':[text]};
""" % js_source_array_engagement

callback = CustomJS(args=engagement_sources, code=code)
slider = Slider(start=days_indices[0], end=days_indices[-1], value=0, step=1, title="Day", callback=callback)

callback.args["renderer_source"] = renderer_source
callback.args["slider"] = slider
callback.args["text_source"] = text_source

layout_one = layout([[plot], [slider]])

print(engagement_sources['_0'].data['days'][0]) #prints (08/28/2019)
print(engagement_sources['_1'].data['days'][0]) #prints (08/29/2019)

plots = row(layout_one, plot_two)

When I move the slider to 0 or 1, the console prints 0 and 1 respectively.

However, they they both map to the date 08/29/2019. I checked if the values are correct by printing them, and the two printing statements show (08/28/2019) and (08/29/2019) respectively.

As a result, I think there could be something wrong with the Callback's code, specifically, how the code is referencing the sources object, but I couldnt figure out what it is, especially since it references all other values correctly except for when the slider is at 0.

Kami Kaze
  • 2,069
  • 15
  • 27

1 Answers1

0

If you are following that example, using show then you are generating standalone output. That is a mode where Bokeh creates a pile of static HTML and JS code and that is sent to a browser to display a plot. But here is the important part: no connection is maintained with any Python process. Updating the slider with this kind of usage only affects JavaScript state, it can have no effect at all on any Python variables or state. If you want to have full, two-way synchronization between Python and the displayed content (which exists on the "JavaScript side") then that is what the Bokeh server is for (that is exactly its purpose).

You can see an example of how to embed a Bokeh server app in the notebook here:

https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/notebook_embed.ipynb

Additionally the tutorial you link is fairly old and employs a very old text-substitution technique that is not at all necessary in a Bokeh server context. You can see the modern (and vastly simpler) Bokeh server version of that Gapminder example here:

https://github.com/bokeh/bokeh/tree/master/examples/app/gapminder

And you can see a live hosted demo of that Gapminder example running here:

https://demo.bokeh.org/gapminder

bigreddot
  • 33,642
  • 5
  • 69
  • 122