Interactive 3D vector visualization with query UI for vector databases
Project description
anywidget-vector
Interactive 3D vector visualization for Python notebooks.
Works with Marimo, Jupyter, VS Code, Colab, anywhere anywidget runs.
Features
- Universal: One widget, every notebook environment
- 6D Visualization: X, Y, Z position + Color, Shape, Size encoding
- Backend-agnostic: NumPy, pandas, Qdrant, Chroma, or raw dicts
- Interactive: Orbit, pan, zoom, click, hover, select
- Customizable: Color scales, shapes, sizes, themes
- Performant: Instanced rendering for large point clouds
Installation
uv add anywidget-vector
Quick Start
from anywidget_vector import VectorSpace
widget = VectorSpace(points=[
{"id": "a", "x": 0.5, "y": 0.3, "z": 0.8, "label": "Point A", "cluster": 0},
{"id": "b", "x": -0.2, "y": 0.7, "z": 0.1, "label": "Point B", "cluster": 1},
{"id": "c", "x": 0.1, "y": -0.4, "z": 0.6, "label": "Point C", "cluster": 0},
])
widget
Data Sources
Dictionary
from anywidget_vector import VectorSpace
widget = VectorSpace.from_dict({
"points": [
{"id": "a", "x": 0, "y": 0, "z": 0},
{"id": "b", "x": 1, "y": 1, "z": 1},
]
})
NumPy Arrays
import numpy as np
from anywidget_vector import VectorSpace
positions = np.random.randn(100, 3)
widget = VectorSpace.from_numpy(positions)
pandas DataFrame
import pandas as pd
from anywidget_vector import VectorSpace
df = pd.DataFrame({
"x": [0.1, 0.5, 0.9],
"y": [0.2, 0.6, 0.3],
"z": [0.3, 0.1, 0.7],
"cluster": ["A", "B", "A"],
"size": [0.5, 1.0, 0.8],
})
widget = VectorSpace.from_dataframe(
df,
color_col="cluster",
size_col="size",
)
UMAP / t-SNE / PCA
import umap
from anywidget_vector import VectorSpace
# Reduce high-dimensional data to 3D
embedding = umap.UMAP(n_components=3).fit_transform(high_dim_data)
widget = VectorSpace.from_umap(embedding, labels=labels)
Qdrant
from qdrant_client import QdrantClient
from anywidget_vector import VectorSpace
client = QdrantClient("localhost", port=6333)
widget = VectorSpace.from_qdrant(client, "my_collection", limit=5000)
ChromaDB
import chromadb
from anywidget_vector import VectorSpace
client = chromadb.Client()
collection = client.get_collection("embeddings")
widget = VectorSpace.from_chroma(collection)
Visual Encoding
6 Dimensions
| Dimension | Visual Channel | Example |
|---|---|---|
| X | Horizontal position | x coordinate |
| Y | Vertical position | y coordinate |
| Z | Depth position | z coordinate |
| Color | Hue/gradient | Cluster, score |
| Shape | Geometry | Category, type |
| Size | Scale | Importance, count |
Color Scales
widget = VectorSpace(
points=data,
color_field="score", # Field to map
color_scale="viridis", # Scale: viridis, plasma, inferno, magma, cividis, turbo
color_domain=[0, 100], # Optional: explicit range
)
Shapes
widget = VectorSpace(
points=data,
shape_field="category",
shape_map={
"type_a": "sphere", # Available: sphere, cube, cone,
"type_b": "cube", # tetrahedron, octahedron, cylinder
"type_c": "cone",
}
)
Size
widget = VectorSpace(
points=data,
size_field="importance",
size_range=[0.02, 0.15], # Min/max point size
)
Interactivity
Events
widget = VectorSpace(points=data)
@widget.on_click
def handle_click(point_id, point_data):
print(f"Clicked: {point_id}")
print(f"Data: {point_data}")
@widget.on_hover
def handle_hover(point_id, point_data):
if point_id:
print(f"Hovering: {point_id}")
@widget.on_selection
def handle_selection(point_ids, points_data):
print(f"Selected {len(point_ids)} points")
Selection
widget.selected_points # Get current selection
widget.select(["a", "b"]) # Select points
widget.clear_selection() # Clear
Camera
widget.camera_position # Get position [x, y, z]
widget.camera_target # Get target [x, y, z]
widget.reset_camera() # Reset to default
widget.focus_on(["a", "b"]) # Focus on specific points
Options
widget = VectorSpace(
points=data,
width=1000,
height=700,
background="#1a1a2e", # Dark theme default
show_axes=True,
show_grid=True,
axis_labels={"x": "PC1", "y": "PC2", "z": "PC3"},
show_tooltip=True,
tooltip_fields=["label", "x", "y", "z", "cluster"],
selection_mode="click", # "click" or "multi"
use_instancing=True, # Performance: instanced rendering
)
Distance Metrics
Compute distances and visualize similarity relationships between points.
Supported Metrics
| Metric | Description |
|---|---|
euclidean |
Straight-line distance (L2 norm) |
cosine |
Angle-based distance (1 - cosine similarity) |
manhattan |
Sum of absolute differences (L1 norm) |
dot_product |
Negative dot product (higher = closer) |
Color by Distance
# Color points by distance from a reference
widget.color_by_distance("point_a")
widget.color_by_distance("point_a", metric="cosine")
Find Neighbors
# Find k nearest neighbors
neighbors = widget.find_neighbors("point_a", k=5)
# Returns: [("point_b", 0.1), ("point_c", 0.2), ...]
# Find neighbors within distance threshold
neighbors = widget.find_neighbors("point_a", threshold=0.5)
Show Connections
# Draw lines to k-nearest neighbors
widget.show_neighbors("point_a", k=5)
# Draw lines to all points within threshold
widget.show_neighbors("point_a", threshold=0.3)
# Manual connection settings
widget = VectorSpace(
points=data,
show_connections=True,
k_neighbors=3,
distance_metric="cosine",
connection_color="#00ff00",
connection_opacity=0.5,
)
Compute Distances
# Get distances from reference to all points
distances = widget.compute_distances("point_a")
# Returns: {"point_b": 0.1, "point_c": 0.5, ...}
# Use high-dimensional vectors (not just x,y,z)
distances = widget.compute_distances(
"point_a",
metric="cosine",
vector_field="embedding" # Use full embedding vector
)
Export
widget.to_json() # Export points as JSON string
Environment Support
| Environment | Supported |
|---|---|
| Marimo | ✅ |
| JupyterLab | ✅ |
| Jupyter Notebook | ✅ |
| VS Code | ✅ |
| Google Colab | ✅ |
| Databricks | ✅ |
Related
- anywidget, custom Jupyter widgets made easy
- anywidget-graph, graph visualization widget
- Three.js, 3D JavaScript library
License
Apache-2.0
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 anywidget_vector-0.2.2.tar.gz.
File metadata
- Download URL: anywidget_vector-0.2.2.tar.gz
- Upload date:
- Size: 174.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a164d288f09728219226c6acf1fe3f8e2f1ce89ac30603b9a3b70b89b3c798ff
|
|
| MD5 |
9ac2471892452b6d130f2bf1cf95122e
|
|
| BLAKE2b-256 |
2d70890e78b6f3cc2dd3d391f34f18394a5da6b589d349a04f0c2c01395e2a78
|
Provenance
The following attestation bundles were made for anywidget_vector-0.2.2.tar.gz:
Publisher:
pypi.yml on GrafeoDB/anywidget-vector
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
anywidget_vector-0.2.2.tar.gz -
Subject digest:
a164d288f09728219226c6acf1fe3f8e2f1ce89ac30603b9a3b70b89b3c798ff - Sigstore transparency entry: 926796903
- Sigstore integration time:
-
Permalink:
GrafeoDB/anywidget-vector@4ea2b832684b1a22790d0793a11d28d171600b6c -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/GrafeoDB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@4ea2b832684b1a22790d0793a11d28d171600b6c -
Trigger Event:
release
-
Statement type:
File details
Details for the file anywidget_vector-0.2.2-py3-none-any.whl.
File metadata
- Download URL: anywidget_vector-0.2.2-py3-none-any.whl
- Upload date:
- Size: 46.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf0e3b499873a255767ee8e64e4c57e85d0dd9a70204c75e71803b502c395756
|
|
| MD5 |
b0495a65aeb9dc4f54a929e7d993ed0d
|
|
| BLAKE2b-256 |
317f9b684ae9cb95b2d2d86a1963dfaa2025f7487dab08955ae43a04a34ef0d1
|
Provenance
The following attestation bundles were made for anywidget_vector-0.2.2-py3-none-any.whl:
Publisher:
pypi.yml on GrafeoDB/anywidget-vector
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
anywidget_vector-0.2.2-py3-none-any.whl -
Subject digest:
bf0e3b499873a255767ee8e64e4c57e85d0dd9a70204c75e71803b502c395756 - Sigstore transparency entry: 926796905
- Sigstore integration time:
-
Permalink:
GrafeoDB/anywidget-vector@4ea2b832684b1a22790d0793a11d28d171600b6c -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/GrafeoDB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@4ea2b832684b1a22790d0793a11d28d171600b6c -
Trigger Event:
release
-
Statement type: