render_embedding_atlas

render_embedding_atlas class

Reactively render an Embedding Atlas explorer.

Usage Source

render_embedding_atlas(
    _fn: Optional[ValueFn[EmbeddingAtlasWidget]] = 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,
    allow_unrestricted_connection: bool = False,
)

@render_embedding_atlas is a decorator that creates a render function – a function that returns the explorer to display and re-runs when the reactive values it reads change:

import pandas as pd
from embedding_atlas.widget import EmbeddingAtlasWidget

from shinywidgets import render_embedding_atlas

df = pd.DataFrame(
    {
        "x": [0.0, 1.0, 0.1],
        "y": [0.0, 1.0, 0.2],
        "text": ["alpha", "beta", "gamma"],
    }
)


@render_embedding_atlas
def atlas():
    return EmbeddingAtlasWidget(df, x="x", y="y", text="text")

The render function should return an embedding_atlas.widget.EmbeddingAtlasWidget (requires pip install 'shinywidgets[embedding_atlas]', which needs Python 3.11 or newer). Unlike the other decorators, a bare data frame isn’t enough to build the widget, so construct it yourself, passing the data frame along with the columns that describe the embedding (e.g., EmbeddingAtlasWidget(df, x="x", y="y", text="text")). The embedding (scatter) view itself requires a browser with WebGPU and its shader-f16 feature (e.g., recent Chrome, Edge, or Firefox); elsewhere, the rest of the explorer still works. The explorer needs room: in a non-filling layout, give the output a height of at least "600px".

Note

Accessing the rendered widget: the render function gains two read-only attributes: .value, the value it most recently returned, and .widget, the rendered EmbeddingAtlasWidget instance.

Responding to user interaction: the filter a user builds in the browser is synced to the widget’s (upstream-internal) _predicate trait: read atlas.selected_rows() for the filtered rows, or atlas.predicate() for the filter as a SQL expression, reactively (atlas.read("_predicate") remains available for the raw trait).

Mutating the widget: the explorer doesn’t respond to trait changes made from Python; to change it, re-render.

Security: the explorer runs its queries by sending SQL from the browser to the widget’s DuckDB connection, and without restrictions any visitor can send arbitrary SQL, including SQL that reads or writes files on the server. To protect against this, the renderer locks down the widget’s connection before display (SET enable_external_access = false; SET lock_configuration = true), so that only the data you gave the widget is reachable. If you locked the connection’s configuration yourself (SET lock_configuration = true), the renderer leaves your configuration untouched. Pass allow_unrestricted_connection=True to opt out of the lockdown (e.g., for a local, single-user app).

Even with the lockdown, a visitor can still send expensive queries, which block the Python process while they run.

Parameters

allow_unrestricted_connection : bool = False

When True, the widget’s DuckDB connection is left as the render function returned it, without the lockdown described above. The default (False) is strongly recommended for deployed apps: an unrestricted connection lets any visitor run arbitrary SQL with the server process’s permissions.

rate_policy : Optional[RatePolicy] = None

How to rate-limit predicate() and selected_rows() (debounced by default) and reactive_read() on the widget: "debounce" or "throttle". None (the default) keeps the debounce, and debounces reactive_read() only if rate_delay is given.

rate_delay : Optional[float] = None

The rate-limit window in seconds (default 0.25). 0 disables rate limiting.

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 (see fill and fillable).

fill : Optional[bool] = None

Whether the output should grow or shrink to fit its parent container. When None (the default), this is True if height is not specified.

fillable : Optional[bool] = None

Whether the output container should fill available space (scrolling its contents on overflow). When None (the default), this is True if height is not specified.

Each :
which :

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

predicate() The explorer’s current cross-filter as a DuckDB SQL boolean expression (e.g. (("group")::TEXT IS NOT DISTINCT FROM 'c')), or None when nothing is filtered. Built from every chart’s clicks and brushes and the embedding view’s lasso.
selected_rows() The rows passing the explorer’s current cross-filter (see predicate()), as the same frame type (pandas or polars) the EmbeddingAtlasWidget was built from, including a __row_index__ column of positions into the original frame.

predicate()

render_embedding_atlas.predicate()

The explorer’s current cross-filter as a DuckDB SQL boolean expression (e.g. (("group")::TEXT IS NOT DISTINCT FROM 'c')), or None when nothing is filtered. Built from every chart’s clicks and brushes and the embedding view’s lasso.

For pushing the filter into your own SQL or aggregation; use selected_rows() for the filtered rows themselves. Debounced (250 ms) by default; see the rate_policy and rate_delay parameters.

selected_rows()

render_embedding_atlas.selected_rows()

The rows passing the explorer’s current cross-filter (see predicate()), as the same frame type (pandas or polars) the EmbeddingAtlasWidget was built from, including a __row_index__ column of positions into the original frame.

All rows while nothing is filtered (library semantics). Computed from the same published filter predicate() reports, so the two always describe the same selection, even mid-debounce. Runs a DuckDB query per call, so read it in a @reactive.calc when several outputs need it. Debounced (250 ms) by default.