3D scatter widget with lasso selection
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scatter3d_anywidget-0.1.14.tar.gz.
File metadata
- Download URL: scatter3d_anywidget-0.1.14.tar.gz
- Upload date:
- Size: 209.1 kB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea5273fe1c1ab30391842c8f3a335a4a8bcabe7aa51fc3f11655b0f9d956e3d4
|
|
| MD5 |
87fb80f97632b2b918b9bc32a2701225
|
|
| BLAKE2b-256 |
e481b96e04d8323d09e8765e272688b809c64240e935a3f2cb8c7971decc3960
|
File details
Details for the file scatter3d_anywidget-0.1.14-py3-none-any.whl.
File metadata
- Download URL: scatter3d_anywidget-0.1.14-py3-none-any.whl
- Upload date:
- Size: 210.4 kB
- Tags: Python 3
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bda660de0bc5a8d83f315ea5482d95d1e298618801bb1d5451d46a90b256080f
|
|
| MD5 |
5b04a85015191449e089cca4320243d0
|
|
| BLAKE2b-256 |
35af145c7b7a26425a51935020db93691f73a884c5ce620dd33826e5c713fd07
|