render_ipyvolume
render_ipyvolume class
Reactively render an ipyvolume 3D plot.
Usage Source
render_ipyvolume(
_fn: Optional[ValueFn[ValueT]] = None,
*,
width: Optional[str] = None,
height: Optional[str] = None,
fill: Optional[bool] = None,
fillable: Optional[bool] = None,
rate_policy: Optional[RatePolicy] = None,
rate_delay: Optional[float] = None,
)@render_ipyvolume is a decorator that creates a render function – a function that returns the plot to display and re-runs when the reactive values it reads change:
import ipyvolume as ipv
from shinywidgets import render_ipyvolume
@render_ipyvolume
def plot():
return ipv.quickscatter([0, 1, 2], [0, 1, 0], [1, 0, 1])The render function may return an ipyvolume.Figure widget (requires pip install 'shinywidgets[ipyvolume]'; ipyvolume 0.6.3 also needs ipython_genutils, which it doesn’t declare, so the extra installs it for you). Both ways of getting one work: the pylab API (return ipv.gcf() after drawing, or the container returned by ipv.quickscatter()/ ipv.gcc(), which is unwrapped to its figure) or direct construction (ipyvolume.Figure, with ipyvolume.widgets.Scatter and friends added to fig.scatters). Either way, call the constructors inside the render function: the pylab functions draw on a module-level “current figure”, so figures created elsewhere can end up shared across sessions. With direct construction, set size_selected/color_selected explicitly on scatters – their trait defaults are 0-d numpy arrays, which don’t JSON-serialize – and set fig.xlim/fig.ylim/fig.zlim, since directly constructed figures default to a [0, 1]^3 axis box with no auto-fit. In a filling layout, the figure’s WebGL canvas is resized to fill its container (and tracks container resizes) unless the figure has an explicit width or height.
Note
Accessing the rendered widget: the render function gains two read-only attributes: .value, the value it most recently returned, and .widget, the rendered ipyvolume.Figure instance.
Responding to user interaction: plot.camera() reads the live camera after every orbit, much like input.my_slider() reads an input. Call it in a reactive function (a @render.* function, @reactive.calc, or @reactive.effect), which then re-runs whenever the camera changes. (reactive_read(plot.widget.camera, "position") is the per-trait alternative, since the camera instance never changes.) For selections, register a callback with plot.widget.on_selection(fn) (selections arrive as custom messages, not trait changes) and set a reactive.value inside it.
Mutating the widget: use .widget to update the rendered figure in place; trait changes on the widget are synced to the browser.
Parameters
width : Optional[str] = None-
A CSS length unit (e.g.,
"400px"or"100%") for the output’s width. height : Optional[str] = None-
A CSS length unit for the output’s height. When
None(the default), the output is designed to fill the height of its parent container (seefillandfillable). fill : Optional[bool] = None-
Whether the output should grow or shrink to fit its parent container. When
None(the default), this isTrueifheightis not specified. fillable : Optional[bool] = None-
Whether the output container should fill available space (scrolling its contents on overflow). When
None(the default), this isTrueifheightis not specified. rate_policy : Optional[RatePolicy] = None-
How to rate-limit
reactive_read()on the widget:"debounce"or"throttle".None(the default) debouncesreactive_read()only ifrate_delayis given; no accessor on this renderer declares a default. rate_delay : Optional[float] = None-
The rate-limit window in seconds (default 0.25).
0disables rate limiting.
Examples
import ipyvolume as ipv
import numpy as np
from shiny import App, ui
from shinywidgets import output_widget, render_ipyvolume
app_ui = ui.page_fillable(output_widget("plot"))
def server(input, output, session):
@render_ipyvolume
def plot():
x, y, z = np.random.normal(size=(3, 1000))
ipv.quickscatter(x, y, z, size=1, marker="sphere")
return ipv.gcf()
app = App(app_ui, server)out.read("camera") also works, but returns the raw camera snapshot tuple; prefer camera(), which returns the live Camera object.
See also
output_widget(): in Shiny Core, the UI needs this to hold the output (Shiny Express displays it where the render function is defined).
Methods
camera() |
The figure’s live pythreejs.Camera (a PerspectiveCamera by default). |
camera()
render_ipyvolume.camera()The figure’s live pythreejs.Camera (a PerspectiveCamera by default).
Readers are invalidated when its position/quaternion/zoom change (at the end of each orbit) or the camera is replaced. Reading before the first render cancels silently (like req(False)), as does reading while the figure has no camera (fig.camera = None). The returned object is the same mutable instance across reads – copy what you keep. Not rate-limited (the browser syncs once per orbit); the renderer’s rate_policy/rate_delay affect only reactive_read() – no accessor on this renderer declares a default rate limit.