scatter3d-anywidget
Interactive 3D scatter plots for Python notebooks, with lasso-based selection and categorical annotation.
scatter3d-anywidget provides a high-performance, WebGL-based 3D scatter plot widget built on top of anywidget.
It is designed for exploratory data analysis workflows where users need to interactively select, assign, and modify categories on point clouds.
Features
- 3D scatter visualization (WebGL / Three.js) (up to tens of thousands of points)
- Lasso selection with add and remove operations
- Categorical annotation backed by pandas or Polars Series thanks to narwhals
- Bidirectional sync between Python state and frontend
- Designed for anywidget, works well with marimo and Jupyter
Project status
⚠️ Alpha status, this is alpha software that we are using in our research.
This project is under active development.
APIs, traitlets, and frontend behavior may change without notice.
Contributions and feedback are welcome.
Installation
pip install scatter3d-anywidget
Requirements
- Python ≥ 3.13
- Jupyter or marimo
- WebGL-capable browser
Basic usage
Below is a minimal example showing how to:
- Create a 3D scatter plot
- Attach a categorical variable
- Modify category labels programmatically
- Inspect lasso selections from Python
import random
import numpy as np
import pandas as pd
import marimo
from scatter3d import Scatter3dWidget, Category, LabelListErrorResponse
num_points = 10_000
# Generate random 3D points
points = np.random.randn(num_points, 3)
# Create a categorical variable
species_list = ["species1", "species2", "species3"]
species = random.choices(species_list, k=num_points)
species = Category(pd.Series(species, name="species"))
# Create the widget
w = Scatter3dWidget(xyz=points, category=species)
w.point_size = 0.15
# Modify allowed labels
species.set_label_list(
["species1"],
on_missing_labels=LabelListErrorResponse.SET_MISSING,
)
species.set_label_list(["species1", "species4"])
# Display in marimo / Jupyter
ui = marimo.ui.anywidget(w)
ui
After interacting with the plot (e.g. lasso selection), you can inspect results from Python:
# Result of the last lasso operation
ui.lasso_result_t
# Category statistics
print(species.values.value_counts())
print(species.num_unassigned)
Interactive operation
The widget is fully interactive and designed for exploratory annotation workflows. Users can rotate, pan, and zoom the 3D point cloud directly with the mouse. A lasso tool allows drawing a free-form polygon in screen space to select subsets of points. Once a lasso selection is completed, the selection can be applied to the active category using add or remove operations, updating both the visual state and the underlying Python Category object. All interactions are bidirectionally synchronized: changes made via the UI are immediately reflected in Python, and programmatic updates from Python are propagated back to the frontend. This enables tight interactive loops where visual inspection, manual selection, and scripted analysis coexist seamlessly.
Concepts
Scatter3dWidget
The main widget. It owns the point cloud, rendering state, and interaction logic.
Category
A wrapper around a categorical vector (pandas or Polars Series) that:
- Encodes categories efficiently
- Tracks unassigned values
Categoryobjects are stateful: updating them updates the widget, and vice versa.
Lasso interaction
The lasso tool allows:
- Selecting points in screen space
- Adding or removing points from a category
- Reading back selection results in Python
License
MIT
Metadata
Release files for scatter3d-anywidget 0.1.14
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| scatter3d_anywidget-0.1.14.tar.gz | 209.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| scatter3d_anywidget-0.1.14-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 419.4 kB
Release files / scatter3d_anywidget-0.1.14.tar.gz
| Download URL | scatter3d_anywidget-0.1.14.tar.gz |
|---|---|
| Size | 209.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ea5273fe1c1ab30391842c8f3a335a4a8bcabe7aa51fc3f11655b0f9d956e3d4
|
|
BLAKE2b-256 checksum How to use checksums |
e481b96e04d8323d09e8765e272688b809c64240e935a3f2cb8c7971decc3960
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / scatter3d_anywidget-0.1.14-py3-none-any.whl
| Download URL | scatter3d_anywidget-0.1.14-py3-none-any.whl |
|---|---|
| Size | 210.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bda660de0bc5a8d83f315ea5482d95d1e298618801bb1d5451d46a90b256080f
|
|
BLAKE2b-256 checksum How to use checksums |
35af145c7b7a26425a51935020db93691f73a884c5ce620dd33826e5c713fd07
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|