Skip to main content

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.

anywidget-vector demo

Features

  • Universal: One widget, every notebook environment
  • 6D Visualization: X, Y, Z position + Color, Shape, Size encoding
  • Backend-agnostic: NumPy, pandas, Qdrant, Chroma, Pinecone, Weaviate, LanceDB, or raw dicts
  • Interactive: Orbit, pan, zoom, click, hover, box 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

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

positions = np.random.randn(100, 3)
widget = VectorSpace.from_numpy(positions)

pandas DataFrame

import pandas as pd

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

embedding = umap.UMAP(n_components=3).fit_transform(high_dim_data)
widget = VectorSpace.from_umap(embedding, labels=labels)

Qdrant

from qdrant_client import QdrantClient

client = QdrantClient("localhost", port=6333)
widget = VectorSpace.from_qdrant(client, "my_collection", limit=5000)

ChromaDB

import chromadb

client = chromadb.Client()
collection = client.get_collection("embeddings")
widget = VectorSpace.from_chroma(collection)

Pinecone

from pinecone import Pinecone

pc = Pinecone(api_key="...")
index = pc.Index("my-index")
widget = VectorSpace.from_pinecone(index, limit=5000)

Weaviate

import weaviate

client = weaviate.Client("http://localhost:8080")
widget = VectorSpace.from_weaviate(client, "Article", limit=5000)

LanceDB

import lancedb

db = lancedb.connect("~/.lancedb")
table = db.open_table("vectors")
widget = VectorSpace.from_lancedb(table, limit=5000)

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}")

@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              # Current selection
widget.select(["a", "b"])           # Select points
widget.clear_selection()            # Clear
widget.selection_mode = "box"       # Switch to box-select mode

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

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

widget.color_by_distance("point_a")
widget.color_by_distance("point_a", metric="cosine")

Find Neighbors

neighbors = widget.find_neighbors("point_a", k=5)
# Returns: [("point_b", 0.1), ("point_c", 0.2), ...]

neighbors = widget.find_neighbors("point_a", threshold=0.5)

Show Connections

widget.show_neighbors("point_a", k=5)
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

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"
)

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", "multi", or "box"
    use_instancing=True,          # Performance: instanced rendering
)

Backends

Configure a backend for interactive querying:

widget.set_backend("chroma", client=collection)
widget.set_backend("lancedb", client=table)
widget.set_backend("grafeo", client=db)

Export

widget.to_json()                            # Points as JSON string
widget.to_html()                            # Self-contained HTML string
widget.to_html(title="My Vectors")          # Custom title
widget.save_html("vectors.html")            # Write HTML to file

Environment Support

Environment Supported
Marimo Yes
JupyterLab Yes
Jupyter Notebook Yes
VS Code Yes
Google Colab Yes
Databricks Yes

Related

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

anywidget_vector-0.2.8.tar.gz (238.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

anywidget_vector-0.2.8-py3-none-any.whl (63.8 kB view details)

Uploaded Python 3

File details

Details for the file anywidget_vector-0.2.8.tar.gz.

File metadata

  • Download URL: anywidget_vector-0.2.8.tar.gz
  • Upload date:
  • Size: 238.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for anywidget_vector-0.2.8.tar.gz
Algorithm Hash digest
SHA256 2cef908abfc62e879238ac5d5a179487aeeb36f49cd482aa689674ff69cbda42
MD5 9c6ad2485f3767702648c2e51206dc46
BLAKE2b-256 563d3d51dce7b02185e3b5706c872df7e653dae65a6e0523272be54f10e01f0a

See more details on using hashes here.

Provenance

The following attestation bundles were made for anywidget_vector-0.2.8.tar.gz:

Publisher: pypi.yml on GrafeoDB/anywidget-vector

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file anywidget_vector-0.2.8-py3-none-any.whl.

File metadata

File hashes

Hashes for anywidget_vector-0.2.8-py3-none-any.whl
Algorithm Hash digest
SHA256 05737bcecaf6a416c0846e1b90f3a2fe4f04fc5d008b18ede3f9ef3880c9397d
MD5 3da95f479e729277e52f03875197a6a1
BLAKE2b-256 931783447734694718b02e3f1c6aef219c9fd63dd44dc0409e4cfbab778be9a3

See more details on using hashes here.

Provenance

The following attestation bundles were made for anywidget_vector-0.2.8-py3-none-any.whl:

Publisher: pypi.yml on GrafeoDB/anywidget-vector

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page