anywidget-vector 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.so
5
+ .Python
6
+ build/
7
+ develop-eggs/
8
+ dist/
9
+ downloads/
10
+ eggs/
11
+ .eggs/
12
+ lib/
13
+ lib64/
14
+ parts/
15
+ sdist/
16
+ var/
17
+ wheels/
18
+ *.cl*/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ .venv/
23
+ venv/
24
+ ENV/
25
+ .env
26
+ *.log
27
+ .coverage
28
+ htmlcov/
29
+ .pytest_cache/
30
+ .ruff_cache/
31
+ .mypy_cache/
32
+ .ty/
33
+ node_modules/
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,292 @@
1
+ Metadata-Version: 2.4
2
+ Name: anywidget-vector
3
+ Version: 0.1.0
4
+ Summary: Interactive vector visualization for Python notebooks using anywidget
5
+ Project-URL: Homepage, https://grafeo.dev/
6
+ Project-URL: Repository, https://github.com/GrafeoDB/anywidget-vector
7
+ Author-email: "S.T. Grond" <widget@grafeo.dev>
8
+ License: Apache-2.0
9
+ Keywords: anywidget,jupyter,marimo,vector,visualization
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Framework :: Jupyter
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Scientific/Engineering :: Visualization
20
+ Requires-Python: >=3.12
21
+ Requires-Dist: anywidget>=0.9.21
22
+ Provides-Extra: all
23
+ Requires-Dist: chromadb>=0.4; extra == 'all'
24
+ Requires-Dist: numpy>=1.24; extra == 'all'
25
+ Requires-Dist: pandas>=2.0; extra == 'all'
26
+ Requires-Dist: qdrant-client>=1.0; extra == 'all'
27
+ Provides-Extra: chroma
28
+ Requires-Dist: chromadb>=0.4; extra == 'chroma'
29
+ Provides-Extra: dev
30
+ Requires-Dist: marimo>=0.19.7; extra == 'dev'
31
+ Requires-Dist: prek>=0.3.1; extra == 'dev'
32
+ Requires-Dist: pytest>=9.0.2; extra == 'dev'
33
+ Requires-Dist: ruff>=0.14.14; extra == 'dev'
34
+ Requires-Dist: ty>=0.0.14; extra == 'dev'
35
+ Provides-Extra: lancedb
36
+ Requires-Dist: lancedb>=0.1; extra == 'lancedb'
37
+ Provides-Extra: numpy
38
+ Requires-Dist: numpy>=1.24; extra == 'numpy'
39
+ Provides-Extra: pandas
40
+ Requires-Dist: pandas>=2.0; extra == 'pandas'
41
+ Provides-Extra: pinecone
42
+ Requires-Dist: pinecone-client>=3.0; extra == 'pinecone'
43
+ Provides-Extra: qdrant
44
+ Requires-Dist: qdrant-client>=1.0; extra == 'qdrant'
45
+ Provides-Extra: weaviate
46
+ Requires-Dist: weaviate-client>=4.0; extra == 'weaviate'
47
+ Description-Content-Type: text/markdown
48
+
49
+ # anywidget-vector
50
+
51
+ Interactive 3D vector visualization for Python notebooks.
52
+
53
+ Works with Marimo, Jupyter, VS Code, Colab, anywhere [anywidget](https://anywidget.dev/) runs.
54
+
55
+ ## Features
56
+
57
+ - **Universal** — One widget, every notebook environment
58
+ - **6D Visualization** — X, Y, Z position + Color, Shape, Size encoding
59
+ - **Backend-agnostic** — NumPy, pandas, Qdrant, Chroma, or raw dicts
60
+ - **Interactive** — Orbit, pan, zoom, click, hover, select
61
+ - **Customizable** — Color scales, shapes, sizes, themes
62
+ - **Performant** — Instanced rendering for large point clouds
63
+
64
+ ## Installation
65
+
66
+ ```bash
67
+ uv add anywidget-vector
68
+ ```
69
+
70
+ ## Quick Start
71
+
72
+ ```python
73
+ from anywidget_vector import VectorSpace
74
+
75
+ widget = VectorSpace(points=[
76
+ {"id": "a", "x": 0.5, "y": 0.3, "z": 0.8, "label": "Point A", "cluster": 0},
77
+ {"id": "b", "x": -0.2, "y": 0.7, "z": 0.1, "label": "Point B", "cluster": 1},
78
+ {"id": "c", "x": 0.1, "y": -0.4, "z": 0.6, "label": "Point C", "cluster": 0},
79
+ ])
80
+
81
+ widget
82
+ ```
83
+
84
+ ## Data Sources
85
+
86
+ ### Dictionary
87
+
88
+ ```python
89
+ from anywidget_vector import VectorSpace
90
+
91
+ widget = VectorSpace.from_dict({
92
+ "points": [
93
+ {"id": "a", "x": 0, "y": 0, "z": 0},
94
+ {"id": "b", "x": 1, "y": 1, "z": 1},
95
+ ]
96
+ })
97
+ ```
98
+
99
+ ### NumPy Arrays
100
+
101
+ ```python
102
+ import numpy as np
103
+ from anywidget_vector import VectorSpace
104
+
105
+ positions = np.random.randn(100, 3)
106
+ widget = VectorSpace.from_numpy(positions)
107
+ ```
108
+
109
+ ### pandas DataFrame
110
+
111
+ ```python
112
+ import pandas as pd
113
+ from anywidget_vector import VectorSpace
114
+
115
+ df = pd.DataFrame({
116
+ "x": [0.1, 0.5, 0.9],
117
+ "y": [0.2, 0.6, 0.3],
118
+ "z": [0.3, 0.1, 0.7],
119
+ "cluster": ["A", "B", "A"],
120
+ "size": [0.5, 1.0, 0.8],
121
+ })
122
+
123
+ widget = VectorSpace.from_dataframe(
124
+ df,
125
+ color_col="cluster",
126
+ size_col="size",
127
+ )
128
+ ```
129
+
130
+ ### UMAP / t-SNE / PCA
131
+
132
+ ```python
133
+ import umap
134
+ from anywidget_vector import VectorSpace
135
+
136
+ # Reduce high-dimensional data to 3D
137
+ embedding = umap.UMAP(n_components=3).fit_transform(high_dim_data)
138
+ widget = VectorSpace.from_umap(embedding, labels=labels)
139
+ ```
140
+
141
+ ### Qdrant
142
+
143
+ ```python
144
+ from qdrant_client import QdrantClient
145
+ from anywidget_vector import VectorSpace
146
+
147
+ client = QdrantClient("localhost", port=6333)
148
+ widget = VectorSpace.from_qdrant(client, "my_collection", limit=5000)
149
+ ```
150
+
151
+ ### ChromaDB
152
+
153
+ ```python
154
+ import chromadb
155
+ from anywidget_vector import VectorSpace
156
+
157
+ client = chromadb.Client()
158
+ collection = client.get_collection("embeddings")
159
+ widget = VectorSpace.from_chroma(collection)
160
+ ```
161
+
162
+ ## Visual Encoding
163
+
164
+ ### 6 Dimensions
165
+
166
+ | Dimension | Visual Channel | Example |
167
+ |-----------|---------------|---------|
168
+ | X | Horizontal position | `x` coordinate |
169
+ | Y | Vertical position | `y` coordinate |
170
+ | Z | Depth position | `z` coordinate |
171
+ | Color | Hue/gradient | Cluster, score |
172
+ | Shape | Geometry | Category, type |
173
+ | Size | Scale | Importance, count |
174
+
175
+ ### Color Scales
176
+
177
+ ```python
178
+ widget = VectorSpace(
179
+ points=data,
180
+ color_field="score", # Field to map
181
+ color_scale="viridis", # Scale: viridis, plasma, inferno, magma, cividis, turbo
182
+ color_domain=[0, 100], # Optional: explicit range
183
+ )
184
+ ```
185
+
186
+ ### Shapes
187
+
188
+ ```python
189
+ widget = VectorSpace(
190
+ points=data,
191
+ shape_field="category",
192
+ shape_map={
193
+ "type_a": "sphere", # Available: sphere, cube, cone,
194
+ "type_b": "cube", # tetrahedron, octahedron, cylinder
195
+ "type_c": "cone",
196
+ }
197
+ )
198
+ ```
199
+
200
+ ### Size
201
+
202
+ ```python
203
+ widget = VectorSpace(
204
+ points=data,
205
+ size_field="importance",
206
+ size_range=[0.02, 0.15], # Min/max point size
207
+ )
208
+ ```
209
+
210
+ ## Interactivity
211
+
212
+ ### Events
213
+
214
+ ```python
215
+ widget = VectorSpace(points=data)
216
+
217
+ @widget.on_click
218
+ def handle_click(point_id, point_data):
219
+ print(f"Clicked: {point_id}")
220
+ print(f"Data: {point_data}")
221
+
222
+ @widget.on_hover
223
+ def handle_hover(point_id, point_data):
224
+ if point_id:
225
+ print(f"Hovering: {point_id}")
226
+
227
+ @widget.on_selection
228
+ def handle_selection(point_ids, points_data):
229
+ print(f"Selected {len(point_ids)} points")
230
+ ```
231
+
232
+ ### Selection
233
+
234
+ ```python
235
+ widget.selected_points # Get current selection
236
+ widget.select(["a", "b"]) # Select points
237
+ widget.clear_selection() # Clear
238
+ ```
239
+
240
+ ### Camera
241
+
242
+ ```python
243
+ widget.camera_position # Get position [x, y, z]
244
+ widget.camera_target # Get target [x, y, z]
245
+ widget.reset_camera() # Reset to default
246
+ widget.focus_on(["a", "b"]) # Focus on specific points
247
+ ```
248
+
249
+ ## Options
250
+
251
+ ```python
252
+ widget = VectorSpace(
253
+ points=data,
254
+ width=1000,
255
+ height=700,
256
+ background="#1a1a2e", # Dark theme default
257
+ show_axes=True,
258
+ show_grid=True,
259
+ axis_labels={"x": "PC1", "y": "PC2", "z": "PC3"},
260
+ show_tooltip=True,
261
+ tooltip_fields=["label", "x", "y", "z", "cluster"],
262
+ selection_mode="click", # "click" or "multi"
263
+ use_instancing=True, # Performance: instanced rendering
264
+ )
265
+ ```
266
+
267
+ ## Export
268
+
269
+ ```python
270
+ widget.to_json() # Export points as JSON string
271
+ ```
272
+
273
+ ## Environment Support
274
+
275
+ | Environment | Supported |
276
+ |-------------|-----------|
277
+ | Marimo | ✅ |
278
+ | JupyterLab | ✅ |
279
+ | Jupyter Notebook | ✅ |
280
+ | VS Code | ✅ |
281
+ | Google Colab | ✅ |
282
+ | Databricks | ✅ |
283
+
284
+ ## Related
285
+
286
+ - [anywidget](https://anywidget.dev/) — Custom Jupyter widgets made easy
287
+ - [anywidget-graph](https://github.com/GrafeoDB/anywidget-graph) — Graph visualization widget
288
+ - [Three.js](https://threejs.org/) — 3D JavaScript library
289
+
290
+ ## License
291
+
292
+ Apache-2.0
@@ -0,0 +1,244 @@
1
+ # anywidget-vector
2
+
3
+ Interactive 3D vector visualization for Python notebooks.
4
+
5
+ Works with Marimo, Jupyter, VS Code, Colab, anywhere [anywidget](https://anywidget.dev/) runs.
6
+
7
+ ## Features
8
+
9
+ - **Universal** — One widget, every notebook environment
10
+ - **6D Visualization** — X, Y, Z position + Color, Shape, Size encoding
11
+ - **Backend-agnostic** — NumPy, pandas, Qdrant, Chroma, or raw dicts
12
+ - **Interactive** — Orbit, pan, zoom, click, hover, select
13
+ - **Customizable** — Color scales, shapes, sizes, themes
14
+ - **Performant** — Instanced rendering for large point clouds
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ uv add anywidget-vector
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ```python
25
+ from anywidget_vector import VectorSpace
26
+
27
+ widget = VectorSpace(points=[
28
+ {"id": "a", "x": 0.5, "y": 0.3, "z": 0.8, "label": "Point A", "cluster": 0},
29
+ {"id": "b", "x": -0.2, "y": 0.7, "z": 0.1, "label": "Point B", "cluster": 1},
30
+ {"id": "c", "x": 0.1, "y": -0.4, "z": 0.6, "label": "Point C", "cluster": 0},
31
+ ])
32
+
33
+ widget
34
+ ```
35
+
36
+ ## Data Sources
37
+
38
+ ### Dictionary
39
+
40
+ ```python
41
+ from anywidget_vector import VectorSpace
42
+
43
+ widget = VectorSpace.from_dict({
44
+ "points": [
45
+ {"id": "a", "x": 0, "y": 0, "z": 0},
46
+ {"id": "b", "x": 1, "y": 1, "z": 1},
47
+ ]
48
+ })
49
+ ```
50
+
51
+ ### NumPy Arrays
52
+
53
+ ```python
54
+ import numpy as np
55
+ from anywidget_vector import VectorSpace
56
+
57
+ positions = np.random.randn(100, 3)
58
+ widget = VectorSpace.from_numpy(positions)
59
+ ```
60
+
61
+ ### pandas DataFrame
62
+
63
+ ```python
64
+ import pandas as pd
65
+ from anywidget_vector import VectorSpace
66
+
67
+ df = pd.DataFrame({
68
+ "x": [0.1, 0.5, 0.9],
69
+ "y": [0.2, 0.6, 0.3],
70
+ "z": [0.3, 0.1, 0.7],
71
+ "cluster": ["A", "B", "A"],
72
+ "size": [0.5, 1.0, 0.8],
73
+ })
74
+
75
+ widget = VectorSpace.from_dataframe(
76
+ df,
77
+ color_col="cluster",
78
+ size_col="size",
79
+ )
80
+ ```
81
+
82
+ ### UMAP / t-SNE / PCA
83
+
84
+ ```python
85
+ import umap
86
+ from anywidget_vector import VectorSpace
87
+
88
+ # Reduce high-dimensional data to 3D
89
+ embedding = umap.UMAP(n_components=3).fit_transform(high_dim_data)
90
+ widget = VectorSpace.from_umap(embedding, labels=labels)
91
+ ```
92
+
93
+ ### Qdrant
94
+
95
+ ```python
96
+ from qdrant_client import QdrantClient
97
+ from anywidget_vector import VectorSpace
98
+
99
+ client = QdrantClient("localhost", port=6333)
100
+ widget = VectorSpace.from_qdrant(client, "my_collection", limit=5000)
101
+ ```
102
+
103
+ ### ChromaDB
104
+
105
+ ```python
106
+ import chromadb
107
+ from anywidget_vector import VectorSpace
108
+
109
+ client = chromadb.Client()
110
+ collection = client.get_collection("embeddings")
111
+ widget = VectorSpace.from_chroma(collection)
112
+ ```
113
+
114
+ ## Visual Encoding
115
+
116
+ ### 6 Dimensions
117
+
118
+ | Dimension | Visual Channel | Example |
119
+ |-----------|---------------|---------|
120
+ | X | Horizontal position | `x` coordinate |
121
+ | Y | Vertical position | `y` coordinate |
122
+ | Z | Depth position | `z` coordinate |
123
+ | Color | Hue/gradient | Cluster, score |
124
+ | Shape | Geometry | Category, type |
125
+ | Size | Scale | Importance, count |
126
+
127
+ ### Color Scales
128
+
129
+ ```python
130
+ widget = VectorSpace(
131
+ points=data,
132
+ color_field="score", # Field to map
133
+ color_scale="viridis", # Scale: viridis, plasma, inferno, magma, cividis, turbo
134
+ color_domain=[0, 100], # Optional: explicit range
135
+ )
136
+ ```
137
+
138
+ ### Shapes
139
+
140
+ ```python
141
+ widget = VectorSpace(
142
+ points=data,
143
+ shape_field="category",
144
+ shape_map={
145
+ "type_a": "sphere", # Available: sphere, cube, cone,
146
+ "type_b": "cube", # tetrahedron, octahedron, cylinder
147
+ "type_c": "cone",
148
+ }
149
+ )
150
+ ```
151
+
152
+ ### Size
153
+
154
+ ```python
155
+ widget = VectorSpace(
156
+ points=data,
157
+ size_field="importance",
158
+ size_range=[0.02, 0.15], # Min/max point size
159
+ )
160
+ ```
161
+
162
+ ## Interactivity
163
+
164
+ ### Events
165
+
166
+ ```python
167
+ widget = VectorSpace(points=data)
168
+
169
+ @widget.on_click
170
+ def handle_click(point_id, point_data):
171
+ print(f"Clicked: {point_id}")
172
+ print(f"Data: {point_data}")
173
+
174
+ @widget.on_hover
175
+ def handle_hover(point_id, point_data):
176
+ if point_id:
177
+ print(f"Hovering: {point_id}")
178
+
179
+ @widget.on_selection
180
+ def handle_selection(point_ids, points_data):
181
+ print(f"Selected {len(point_ids)} points")
182
+ ```
183
+
184
+ ### Selection
185
+
186
+ ```python
187
+ widget.selected_points # Get current selection
188
+ widget.select(["a", "b"]) # Select points
189
+ widget.clear_selection() # Clear
190
+ ```
191
+
192
+ ### Camera
193
+
194
+ ```python
195
+ widget.camera_position # Get position [x, y, z]
196
+ widget.camera_target # Get target [x, y, z]
197
+ widget.reset_camera() # Reset to default
198
+ widget.focus_on(["a", "b"]) # Focus on specific points
199
+ ```
200
+
201
+ ## Options
202
+
203
+ ```python
204
+ widget = VectorSpace(
205
+ points=data,
206
+ width=1000,
207
+ height=700,
208
+ background="#1a1a2e", # Dark theme default
209
+ show_axes=True,
210
+ show_grid=True,
211
+ axis_labels={"x": "PC1", "y": "PC2", "z": "PC3"},
212
+ show_tooltip=True,
213
+ tooltip_fields=["label", "x", "y", "z", "cluster"],
214
+ selection_mode="click", # "click" or "multi"
215
+ use_instancing=True, # Performance: instanced rendering
216
+ )
217
+ ```
218
+
219
+ ## Export
220
+
221
+ ```python
222
+ widget.to_json() # Export points as JSON string
223
+ ```
224
+
225
+ ## Environment Support
226
+
227
+ | Environment | Supported |
228
+ |-------------|-----------|
229
+ | Marimo | ✅ |
230
+ | JupyterLab | ✅ |
231
+ | Jupyter Notebook | ✅ |
232
+ | VS Code | ✅ |
233
+ | Google Colab | ✅ |
234
+ | Databricks | ✅ |
235
+
236
+ ## Related
237
+
238
+ - [anywidget](https://anywidget.dev/) — Custom Jupyter widgets made easy
239
+ - [anywidget-graph](https://github.com/GrafeoDB/anywidget-graph) — Graph visualization widget
240
+ - [Three.js](https://threejs.org/) — 3D JavaScript library
241
+
242
+ ## License
243
+
244
+ Apache-2.0
@@ -0,0 +1,101 @@
1
+ [project]
2
+ name = "anywidget-vector"
3
+ version = "0.1.0"
4
+ description = "Interactive vector visualization for Python notebooks using anywidget"
5
+ readme = "README.md"
6
+ license = { text = "Apache-2.0" }
7
+ requires-python = ">=3.12"
8
+ authors = [{ name = "S.T. Grond", email = "widget@grafeo.dev" }]
9
+ keywords = ["anywidget", "vector", "visualization", "jupyter", "marimo"]
10
+ classifiers = [
11
+ "Development Status :: 3 - Alpha",
12
+ "Framework :: Jupyter",
13
+ "Intended Audience :: Developers",
14
+ "Intended Audience :: Science/Research",
15
+ "License :: OSI Approved :: Apache Software License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Programming Language :: Python :: 3.14",
20
+ "Topic :: Scientific/Engineering :: Visualization",
21
+ ]
22
+
23
+ dependencies = [
24
+ "anywidget>=0.9.21",
25
+ ]
26
+
27
+ [project.optional-dependencies]
28
+ dev = [
29
+ "prek>=0.3.1",
30
+ "pytest>=9.0.2",
31
+ "ruff>=0.14.14",
32
+ "ty>=0.0.14",
33
+ "marimo>=0.19.7",
34
+ ]
35
+ pandas = ["pandas>=2.0"]
36
+ numpy = ["numpy>=1.24"]
37
+ qdrant = ["qdrant-client>=1.0"]
38
+ chroma = ["chromadb>=0.4"]
39
+ pinecone = ["pinecone-client>=3.0"]
40
+ weaviate = ["weaviate-client>=4.0"]
41
+ lancedb = ["lancedb>=0.1"]
42
+ all = [
43
+ "pandas>=2.0",
44
+ "numpy>=1.24",
45
+ "qdrant-client>=1.0",
46
+ "chromadb>=0.4",
47
+ ]
48
+
49
+ [project.urls]
50
+ Homepage = "https://grafeo.dev/"
51
+ Repository = "https://github.com/GrafeoDB/anywidget-vector"
52
+
53
+ [build-system]
54
+ requires = ["hatchling"]
55
+ build-backend = "hatchling.build"
56
+
57
+ [tool.hatch.build.targets.wheel]
58
+ packages = ["src/anywidget_vector"]
59
+
60
+ [tool.ruff]
61
+ line-length = 120
62
+ target-version = "py312"
63
+
64
+ [tool.ruff.lint]
65
+ select = [
66
+ "E",
67
+ "F",
68
+ "I",
69
+ "UP",
70
+ "FA",
71
+ "Q",
72
+ ]
73
+
74
+ [tool.ruff.lint.per-file-ignores]
75
+ "src/anywidget_vector/widget.py" = ["E501"] # Long lines in embedded JS
76
+
77
+ [tool.ruff.lint.flake8-quotes]
78
+ inline-quotes = "double"
79
+ docstring-quotes = "double"
80
+
81
+ [tool.ty.environment]
82
+ python-version = "3.12"
83
+
84
+ [tool.pytest.ini_options]
85
+ testpaths = ["tests"]
86
+ pythonpath = ["src"]
87
+ addopts = "-v"
88
+
89
+ [tool.prek]
90
+ repos = [
91
+ { repo = "ruff", hooks = [
92
+ { id = "ruff-check", args = ["--fix", "--exit-non-zero-on-fix"] },
93
+ { id = "ruff-format" },
94
+ ]},
95
+ ]
96
+
97
+ [tool.uv]
98
+ dev-dependencies = [
99
+ "pytest>=9.0.2",
100
+ "ruff>=0.14.14",
101
+ ]
@@ -0,0 +1,6 @@
1
+ """Interactive 3D vector visualization for Python notebooks."""
2
+
3
+ from anywidget_vector.widget import VectorSpace
4
+
5
+ __all__ = ["VectorSpace"]
6
+ __version__ = "0.1.0"
File without changes