How to cause the screen to redraw from within a Bokeh event handler?

Hi

Many thanks for Panel!

I have successfully drawn a screen within a vscode notebook, using a Panel pane.Bokeh(column) where column is a Bokeh column. I have a python event handler there, which also works. It’s code is below, essentially every time the plot is tapped it generates an event and I do actually get the event!

Versions:
Bokeh 3.1.1
vscode 1.79.2
Panel 1.1.1
jupyter_bokeh 3.0.7

The problem: the screen does not refresh, so when I change data based on the tap - there is no change to the screen.

As you can see below, I tried several things, but they do not have the desired effect:

  1. I attempted to add a change.emit, however the Glyph and the ColumnDataSource do not have a change property. Is it possible that the Panel pane “wrapper” has removed the change property?
  2. I tried to use Panel’s pn.io.push_notebook(pane) but it simply has no effect.
  3. I tried to use Panel’s pane.param.trigger('object'), again to no effect

How do I get Panel to refresh the plot from inside the event handler? Thanks!

        def tap_callback(event):
            feature_index = floor(event.y)
            feature_name = event.model.y_range.factors[feature_index]
            new_value = ... # [details removed to avoid confusion]
            
            # making the change show up in the plot
            for r in event.model.renderers:
                if hasattr(r, 'glyph'):
                    r.data_source.data['most important'][-1-feature_index] = new_value
                    if hasattr(r.data_source, 'change'):
                        print('this line is never reached')
                        r.data_source.change.emit()
                    if hasattr(r.glyph, 'change'):
                        print('this line is never reached, either')
                        r.glyph.change.emit()
            
            print('these two line do not seem to do what they should?')
            self.pane.param.trigger('object')
            pn.io.push_notebook(self.pane)

Many thanks
GPN

1 Like

@philippjfr . Would you have some advice on trigger updates of Bokeh object in callback handler?

@Marc I solved this on the Bokeh level, by doing a complete recreation of the ColumnDataSource and then setting the source, like so:

        def tap_callback(event):
            feature_index = floor(event.y)
            feature_name = event.model.y_range.factors[feature_index]
            new_value = ... # ommitted irrelevant details

            # create new dict of all the data
            new_data = {}
            for r in event.model.renderers:
                if hasattr(r, 'glyph'):
                    for c in r.data_source.data:
                        new_data[c] = r.data_source.data[c]
                    new_data['relevant column name'][-1-feature_index] = new_value
                    r.data_source.data = new_data
                    break

I hope someone else benefits from this solution.
Many thanks
GPN

1 Like