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

feat: Bokeh support as FigureBokeh #997

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

rileythai
Copy link

@rileythai rileythai commented Feb 7, 2025

All Submissions:

  • docs/examples
  • pre-commit
  • tests

Description of changes

This PR resolves #202, and adds a solara.lab component to support Bokeh figure and Plot objects. It additionally adds dependencies for bokeh and jupyter_bokeh.

Part of the code is based on the implementation written in #202 by @maartenbreddels.

It behaves similarly to FigurePlotly, except it shows a temporary SpinnerSolara until the plot is ready while the BokehJS backend loads.

Additionally it takes arguments of light_theme and dark_theme to update the theme via a solara-side effect (the document instance must exist for us to update theming via the high-level interface)

This PR adds:

├── solara
│  └── lab
│     └── components
│        ├── bokehloaded.vue
│        └── figurebokeh.py
└───── website
      ├── pages
      │  ├── apps
      │  └────  scatter-bokeh.py
      └──── documentation
            └── examples
               ├── fullscreen
               │  └── scatter_bokeh.py
               └── visualization
                  └── bokeh.py

and modifies relevant files for importing components in lab

Known issues/pitfalls

  • Bokeh does not support an axis type change, so changing axes via high-level interface x_axis_type, etc doesnt work.
    • log workaround: update x_scale and/or y_scale of figure via a use_effect
    • categorical workaround: scale/map data server-side (partially implemented in scatter-bokeh.py example for the colorbar) + update tickers directly.
  • JS-side selection events on a Tool will fail to link to attributes of any bokeh.model if it is regenerated with each render.
    • occurs bokeh.model.tools instance with a callback like CustomJS(args=dict(object=object)), such as object.selected.indices or similar from a ColumnDataSource upon a selection.
    • suggested approach: use_memo models with callbacks to exclude from regeneration, then use use_effect or similar for attribute updates.
  • When embedded in a GridDraggable instance, theming is not applied on first render after it is added.
  • The Bokeh.document instance attempts to cleanup widgets that no longer exist.
    • this happens ocassionally, but leads to tracebacks that clog entire logs because it spits the entire figure object as text. See below:
Traceback (most recent call last):
  File "/ipywidgets/widgets/widget.py", line 516, in __del__
    self.close()
  File "/jupyter_bokeh/widgets.py", line 92, in close
    self._document.remove_on_change(self)
  File "/bokeh/document/document.py", line 592, in remove_on_change
    self.callbacks.remove_on_change(*callbacks)
  File "/bokeh/document/callbacks.py", line 331, in remove_on_change
    del self._change_callbacks[callback]
KeyError: BokehModel(render_bundle={'docs_json': ... # entire figure object comes out here

Copy link
Contributor

@maartenbreddels maartenbreddels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I think @Jhsmit will also like this. Maybe @Jhsmit can also review this?

light_theme: str | Theme = "light_minimal",
dark_theme: str | Theme = "dark_minimal",
):
# NOTE: no docstring because not a component.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not a component? Because if we use this function conditionally, we'll have conditional hooks

Copy link
Author

@rileythai rileythai Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the same reason FigurePlotly isn't a component. If you want to attach an effect callback to the figure widget, you won't be able to access it with sl.get_widget outside of the function itself.

It occurs to me that FigurePlotly is a component, hang on.

Copy link
Author

@rileythai rileythai Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I seem to have it working now as a component

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran into issues relating to #927 on occassion, couldn't track down what caused it

rileythai and others added 7 commits February 11, 2025 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature Request: Bokeh support
2 participants