Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Layout won’t update after curdoc().unhold() #13611

Closed
Icoti opened this issue Dec 18, 2023 · 3 comments · Fixed by #13710
Closed

[BUG] Layout won’t update after curdoc().unhold() #13611

Icoti opened this issue Dec 18, 2023 · 3 comments · Fixed by #13710

Comments

@Icoti
Copy link
Contributor

Icoti commented Dec 18, 2023

Software versions

Python version : 3.12.0 | packaged by conda-forge | (main, Oct 3 2023, 08:26:13) [MSC v.1935 64 bit (AMD64)]
IPython version : 8.16.1
Tornado version : 6.3.3
Bokeh version : 3.3.0
BokehJS static path : C:\Users\XXX\miniconda3\envs\myenv312\Lib\site-packages\bokeh\server\static
node.js version : (not installed)
npm version : (not installed)
Operating system : Windows-10-10.0.19045-SP0

Browser name and version

Chrome Version 120.0.6099.71 (Offizieller Build) (64-Bit)

Jupyter notebook / Jupyter Lab version

No response

Expected behavior

In the following code, I change the source of a plot renderer in a callback.
For performance reasons (which don’t play a role in this minimal example), I first remove the plot from the layout, apply the change and then put the plot back to the layout.
This works fine, but as expected I get a blinking which I would like to avoid, so I use curdoc().hold() - curdoc().unhold().
I would then expect the display to update after curdoc().unhold(), in my example the plot should go to 5000.

Observed behavior

After curdoc().unhold(), the update is not shown.
Also, I get a JavaScript console warning reference already known 'p1002', P1002 being the id of the plot.

Example code

import numpy as np

from bokeh.io import curdoc
from bokeh.plotting import figure, show
from bokeh.layouts import Column
from bokeh.models import Button, ColumnDataSource

button = Button(label="Click")

p = figure(width=400, height=400, title="Title")

small_array = np.arange(1000)
small_dict = dict(x=small_array, y=small_array)
source = ColumnDataSource(small_dict)

big_array = np.arange(50000) # <- Increase this number if the change is too quick on your machine
big_dict = dict(x=big_array, y=big_array)

p.circle(source=source)

def callback():
    curdoc().hold() # <- Toggle
    layout.children = [button]
    p.title.text="New title"
    p.renderers[0].data_source.data = big_dict
    layout.children.append(p)
    curdoc().unhold() # <- Toggle

button.on_click(callback)

layout = Column(button, p)

curdoc().add_root(layout)

Stack traceback or browser console output

For more information about why I remove the plot from the layout, see:
https://discourse.bokeh.org/t/layout-wont-update-after-curdoc-unhold/11109

Browser console output:

bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:184 [bokeh] setting log level to: 'info'
bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:226 [bokeh] Websocket connection 0 is now open
bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:163 Bokeh items were rendered successfully
bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:165 [bokeh] document idle at 125 ms
bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212 [bokeh] reference already known 'p1002'
warning @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
_decode_object_ref @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
_decode @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
(anonymous) @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
h @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:178
_decode_plain_array @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
_decode @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
_decode_plain_object @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
_decode @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
(anonymous) @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
h @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:178
_decode_plain_array @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
_decode @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
(anonymous) @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
decode @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:212
apply_json_patch @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:165
_handle_patch @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:229
handle @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:229
_steady_state_handler @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:226
e.msgtype._current_handler @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:226
_on_message @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:226
socket.onmessage @ bokeh.min.js?v=39ef57c3a83533e24f961e5c27f651a61045dbccefac4b5df86a7680b1edaff31886a7c0322250ffb0d758fa14ae156c9b640f60cca99f020096b050a4dbb571:226

Screenshots

No response

@Icoti Icoti added the TRIAGE label Dec 18, 2023
@philippjfr
Copy link
Contributor

I think the problem here is that when you remove the plot from the layout the property changes on it are no longer tracked this means your updates to the plot do not trigger change events. When you re-add the plot to the layout it internally combines the two change events to the children (dropping the event that removes the plot). When you call unhold only the single Column.children event is sent to the frontend and since that already has a full representation of your plot the event is ignored. You might try changing the hold policy from "combine" to "collect" in the curdoc.hold(policy='collect') call.

@philippjfr
Copy link
Contributor

philippjfr commented Feb 21, 2024

This seems like a potentially general problem with the serializer. @mattpap In a case like this where a reference is already known could we not apply the updated property values from the new reference to the existing model or is that too complex for nested models?

@Icoti
Copy link
Contributor Author

Icoti commented Feb 21, 2024

@philippjfr

You might try changing the hold policy from "combine" to "collect" in the curdoc.hold(policy='collect') call.

I already tried this, but this doesn't change the behavior in my case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants