anywidget-vector 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl
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.
- anywidget_vector/__init__.py +1 -1
- anywidget_vector/widget.py +285 -2
- {anywidget_vector-0.1.0.dist-info → anywidget_vector-0.2.0.dist-info}/METADATA +68 -1
- anywidget_vector-0.2.0.dist-info/RECORD +6 -0
- anywidget_vector-0.1.0.dist-info/RECORD +0 -6
- {anywidget_vector-0.1.0.dist-info → anywidget_vector-0.2.0.dist-info}/WHEEL +0 -0
anywidget_vector/__init__.py
CHANGED
anywidget_vector/widget.py
CHANGED
|
@@ -39,6 +39,33 @@ const SHAPES = {
|
|
|
39
39
|
cylinder: () => new THREE.CylinderGeometry(0.5, 0.5, 1, 16),
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
+
// Distance metrics
|
|
43
|
+
const DISTANCE_METRICS = {
|
|
44
|
+
euclidean: (a, b) => {
|
|
45
|
+
const dx = a.x - b.x, dy = a.y - b.y, dz = a.z - b.z;
|
|
46
|
+
return Math.sqrt(dx*dx + dy*dy + dz*dz);
|
|
47
|
+
},
|
|
48
|
+
cosine: (a, b) => {
|
|
49
|
+
const dot = a.x*b.x + a.y*b.y + a.z*b.z;
|
|
50
|
+
const magA = Math.sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
|
|
51
|
+
const magB = Math.sqrt(b.x*b.x + b.y*b.y + b.z*b.z);
|
|
52
|
+
if (magA === 0 || magB === 0) return 1;
|
|
53
|
+
return 1 - (dot / (magA * magB)); // Convert similarity to distance
|
|
54
|
+
},
|
|
55
|
+
manhattan: (a, b) => {
|
|
56
|
+
return Math.abs(a.x - b.x) + Math.abs(a.y - b.y) + Math.abs(a.z - b.z);
|
|
57
|
+
},
|
|
58
|
+
dot_product: (a, b) => {
|
|
59
|
+
// Negative dot product as distance (higher dot = closer)
|
|
60
|
+
return -(a.x*b.x + a.y*b.y + a.z*b.z);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
function computeDistance(p1, p2, metric) {
|
|
65
|
+
const fn = DISTANCE_METRICS[metric] || DISTANCE_METRICS.euclidean;
|
|
66
|
+
return fn(p1, p2);
|
|
67
|
+
}
|
|
68
|
+
|
|
42
69
|
function getColorFromScale(value, scaleName, domain) {
|
|
43
70
|
const scale = COLOR_SCALES[scaleName] || COLOR_SCALES.viridis;
|
|
44
71
|
const [min, max] = domain || [0, 1];
|
|
@@ -74,7 +101,7 @@ function getCategoricalColor(value) {
|
|
|
74
101
|
|
|
75
102
|
function render({ model, el }) {
|
|
76
103
|
let scene, camera, renderer, controls;
|
|
77
|
-
let pointsGroup;
|
|
104
|
+
let pointsGroup, connectionsGroup;
|
|
78
105
|
let raycaster, mouse;
|
|
79
106
|
let hoveredObject = null;
|
|
80
107
|
let tooltip;
|
|
@@ -127,6 +154,8 @@ function render({ model, el }) {
|
|
|
127
154
|
// Groups
|
|
128
155
|
pointsGroup = new THREE.Group();
|
|
129
156
|
scene.add(pointsGroup);
|
|
157
|
+
connectionsGroup = new THREE.Group();
|
|
158
|
+
scene.add(connectionsGroup);
|
|
130
159
|
axesGroup = new THREE.Group();
|
|
131
160
|
scene.add(axesGroup);
|
|
132
161
|
|
|
@@ -135,6 +164,7 @@ function render({ model, el }) {
|
|
|
135
164
|
setupRaycaster(container);
|
|
136
165
|
setupTooltip(container);
|
|
137
166
|
createPoints();
|
|
167
|
+
createConnections();
|
|
138
168
|
bindModelEvents();
|
|
139
169
|
}
|
|
140
170
|
|
|
@@ -349,6 +379,98 @@ function render({ model, el }) {
|
|
|
349
379
|
}
|
|
350
380
|
}
|
|
351
381
|
|
|
382
|
+
function createConnections() {
|
|
383
|
+
// Clear existing connections
|
|
384
|
+
while (connectionsGroup.children.length > 0) {
|
|
385
|
+
const obj = connectionsGroup.children[0];
|
|
386
|
+
if (obj.geometry) obj.geometry.dispose();
|
|
387
|
+
if (obj.material) obj.material.dispose();
|
|
388
|
+
connectionsGroup.remove(obj);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const points = model.get("points") || [];
|
|
392
|
+
const showConnections = model.get("show_connections");
|
|
393
|
+
const kNeighbors = model.get("k_neighbors") || 0;
|
|
394
|
+
const distanceThreshold = model.get("distance_threshold");
|
|
395
|
+
const referencePoint = model.get("reference_point");
|
|
396
|
+
const distanceMetric = model.get("distance_metric") || "euclidean";
|
|
397
|
+
const connectionColor = model.get("connection_color") || "#ffffff";
|
|
398
|
+
const connectionOpacity = model.get("connection_opacity") || 0.3;
|
|
399
|
+
|
|
400
|
+
if (!showConnections || points.length < 2) return;
|
|
401
|
+
|
|
402
|
+
const material = new THREE.LineBasicMaterial({
|
|
403
|
+
color: new THREE.Color(connectionColor),
|
|
404
|
+
transparent: true,
|
|
405
|
+
opacity: connectionOpacity,
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// If reference point is set, connect to k-nearest or within threshold
|
|
409
|
+
if (referencePoint) {
|
|
410
|
+
const refIdx = points.findIndex(p => p.id === referencePoint);
|
|
411
|
+
if (refIdx === -1) return;
|
|
412
|
+
const ref = points[refIdx];
|
|
413
|
+
|
|
414
|
+
// Compute distances from reference
|
|
415
|
+
const distances = points.map((p, i) => ({
|
|
416
|
+
idx: i,
|
|
417
|
+
point: p,
|
|
418
|
+
dist: i === refIdx ? Infinity : computeDistance(ref, p, distanceMetric)
|
|
419
|
+
})).filter(d => d.dist !== Infinity);
|
|
420
|
+
|
|
421
|
+
// Sort by distance
|
|
422
|
+
distances.sort((a, b) => a.dist - b.dist);
|
|
423
|
+
|
|
424
|
+
// Select neighbors
|
|
425
|
+
let neighbors;
|
|
426
|
+
if (distanceThreshold !== null && distanceThreshold !== undefined) {
|
|
427
|
+
neighbors = distances.filter(d => d.dist <= distanceThreshold);
|
|
428
|
+
} else if (kNeighbors > 0) {
|
|
429
|
+
neighbors = distances.slice(0, kNeighbors);
|
|
430
|
+
} else {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Draw lines
|
|
435
|
+
neighbors.forEach(n => {
|
|
436
|
+
const geometry = new THREE.BufferGeometry();
|
|
437
|
+
const positions = new Float32Array([
|
|
438
|
+
ref.x ?? 0, ref.y ?? 0, ref.z ?? 0,
|
|
439
|
+
n.point.x ?? 0, n.point.y ?? 0, n.point.z ?? 0
|
|
440
|
+
]);
|
|
441
|
+
geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
|
|
442
|
+
const line = new THREE.Line(geometry, material);
|
|
443
|
+
connectionsGroup.add(line);
|
|
444
|
+
});
|
|
445
|
+
} else if (kNeighbors > 0) {
|
|
446
|
+
// Connect each point to its k-nearest neighbors
|
|
447
|
+
points.forEach((p, i) => {
|
|
448
|
+
const distances = points.map((other, j) => ({
|
|
449
|
+
idx: j,
|
|
450
|
+
point: other,
|
|
451
|
+
dist: i === j ? Infinity : computeDistance(p, other, distanceMetric)
|
|
452
|
+
})).filter(d => d.dist !== Infinity);
|
|
453
|
+
|
|
454
|
+
distances.sort((a, b) => a.dist - b.dist);
|
|
455
|
+
const neighbors = distances.slice(0, kNeighbors);
|
|
456
|
+
|
|
457
|
+
neighbors.forEach(n => {
|
|
458
|
+
// Only draw if i < n.idx to avoid duplicate lines
|
|
459
|
+
if (i < n.idx) {
|
|
460
|
+
const geometry = new THREE.BufferGeometry();
|
|
461
|
+
const positions = new Float32Array([
|
|
462
|
+
p.x ?? 0, p.y ?? 0, p.z ?? 0,
|
|
463
|
+
n.point.x ?? 0, n.point.y ?? 0, n.point.z ?? 0
|
|
464
|
+
]);
|
|
465
|
+
geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
|
|
466
|
+
const line = new THREE.Line(geometry, material);
|
|
467
|
+
connectionsGroup.add(line);
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
352
474
|
function setupRaycaster(container) {
|
|
353
475
|
raycaster = new THREE.Raycaster();
|
|
354
476
|
mouse = new THREE.Vector2();
|
|
@@ -500,7 +622,7 @@ function render({ model, el }) {
|
|
|
500
622
|
}
|
|
501
623
|
|
|
502
624
|
function bindModelEvents() {
|
|
503
|
-
model.on("change:points", createPoints);
|
|
625
|
+
model.on("change:points", () => { createPoints(); createConnections(); });
|
|
504
626
|
model.on("change:background", () => {
|
|
505
627
|
scene.background = new THREE.Color(model.get("background"));
|
|
506
628
|
});
|
|
@@ -514,6 +636,15 @@ function render({ model, el }) {
|
|
|
514
636
|
model.on("change:shape_field", createPoints);
|
|
515
637
|
model.on("change:shape_map", createPoints);
|
|
516
638
|
|
|
639
|
+
// Distance/connection related
|
|
640
|
+
model.on("change:show_connections", createConnections);
|
|
641
|
+
model.on("change:k_neighbors", createConnections);
|
|
642
|
+
model.on("change:distance_threshold", createConnections);
|
|
643
|
+
model.on("change:reference_point", createConnections);
|
|
644
|
+
model.on("change:distance_metric", createConnections);
|
|
645
|
+
model.on("change:connection_color", createConnections);
|
|
646
|
+
model.on("change:connection_opacity", createConnections);
|
|
647
|
+
|
|
517
648
|
model.on("change:camera_position", () => {
|
|
518
649
|
const pos = model.get("camera_position");
|
|
519
650
|
if (pos) camera.position.set(pos[0], pos[1], pos[2]);
|
|
@@ -614,6 +745,19 @@ class VectorSpace(anywidget.AnyWidget):
|
|
|
614
745
|
use_instancing = traitlets.Bool(default_value=True).tag(sync=True)
|
|
615
746
|
point_budget = traitlets.Int(default_value=100000).tag(sync=True)
|
|
616
747
|
|
|
748
|
+
# Distance metrics and connections
|
|
749
|
+
distance_metric = traitlets.Unicode(default_value="euclidean").tag(
|
|
750
|
+
sync=True
|
|
751
|
+
) # euclidean, cosine, manhattan, dot_product
|
|
752
|
+
show_connections = traitlets.Bool(default_value=False).tag(sync=True)
|
|
753
|
+
k_neighbors = traitlets.Int(default_value=0).tag(sync=True) # k-nearest neighbors to connect
|
|
754
|
+
distance_threshold = traitlets.Float(default_value=None, allow_none=True).tag(
|
|
755
|
+
sync=True
|
|
756
|
+
) # max distance for connections
|
|
757
|
+
reference_point = traitlets.Unicode(default_value=None, allow_none=True).tag(sync=True) # point ID to measure from
|
|
758
|
+
connection_color = traitlets.Unicode(default_value="#ffffff").tag(sync=True)
|
|
759
|
+
connection_opacity = traitlets.Float(default_value=0.3).tag(sync=True)
|
|
760
|
+
|
|
617
761
|
def __init__(
|
|
618
762
|
self,
|
|
619
763
|
points: list[dict[str, Any]] | None = None,
|
|
@@ -933,6 +1077,145 @@ class VectorSpace(anywidget.AnyWidget):
|
|
|
933
1077
|
"""Clear all selections."""
|
|
934
1078
|
self.selected_points = []
|
|
935
1079
|
|
|
1080
|
+
# === Distance Methods ===
|
|
1081
|
+
|
|
1082
|
+
def compute_distances(
|
|
1083
|
+
self,
|
|
1084
|
+
reference_id: str,
|
|
1085
|
+
metric: str | None = None,
|
|
1086
|
+
vector_field: str = "vector",
|
|
1087
|
+
) -> dict[str, float]:
|
|
1088
|
+
"""Compute distances from a reference point to all other points.
|
|
1089
|
+
|
|
1090
|
+
Args:
|
|
1091
|
+
reference_id: ID of the reference point
|
|
1092
|
+
metric: Distance metric (euclidean, cosine, manhattan, dot_product).
|
|
1093
|
+
If None, uses self.distance_metric
|
|
1094
|
+
vector_field: Field containing the full vector (for high-dim distance).
|
|
1095
|
+
Falls back to x,y,z if not present.
|
|
1096
|
+
|
|
1097
|
+
Returns:
|
|
1098
|
+
Dict mapping point ID to distance from reference
|
|
1099
|
+
"""
|
|
1100
|
+
metric = metric or self.distance_metric
|
|
1101
|
+
ref_point = next((p for p in self.points if p.get("id") == reference_id), None)
|
|
1102
|
+
if not ref_point:
|
|
1103
|
+
return {}
|
|
1104
|
+
|
|
1105
|
+
ref_vec = self._get_vector(ref_point, vector_field)
|
|
1106
|
+
distances = {}
|
|
1107
|
+
|
|
1108
|
+
for point in self.points:
|
|
1109
|
+
if point.get("id") == reference_id:
|
|
1110
|
+
continue
|
|
1111
|
+
vec = self._get_vector(point, vector_field)
|
|
1112
|
+
distances[point.get("id")] = self._compute_distance(ref_vec, vec, metric)
|
|
1113
|
+
|
|
1114
|
+
return distances
|
|
1115
|
+
|
|
1116
|
+
def find_neighbors(
|
|
1117
|
+
self,
|
|
1118
|
+
reference_id: str,
|
|
1119
|
+
k: int | None = None,
|
|
1120
|
+
threshold: float | None = None,
|
|
1121
|
+
metric: str | None = None,
|
|
1122
|
+
vector_field: str = "vector",
|
|
1123
|
+
) -> list[tuple[str, float]]:
|
|
1124
|
+
"""Find nearest neighbors of a reference point.
|
|
1125
|
+
|
|
1126
|
+
Args:
|
|
1127
|
+
reference_id: ID of the reference point
|
|
1128
|
+
k: Number of neighbors to return (if None, uses threshold)
|
|
1129
|
+
threshold: Maximum distance (if None, uses k)
|
|
1130
|
+
metric: Distance metric to use
|
|
1131
|
+
vector_field: Field containing the full vector
|
|
1132
|
+
|
|
1133
|
+
Returns:
|
|
1134
|
+
List of (point_id, distance) tuples, sorted by distance
|
|
1135
|
+
"""
|
|
1136
|
+
distances = self.compute_distances(reference_id, metric, vector_field)
|
|
1137
|
+
sorted_distances = sorted(distances.items(), key=lambda x: x[1])
|
|
1138
|
+
|
|
1139
|
+
if threshold is not None:
|
|
1140
|
+
return [(pid, d) for pid, d in sorted_distances if d <= threshold]
|
|
1141
|
+
elif k is not None:
|
|
1142
|
+
return sorted_distances[:k]
|
|
1143
|
+
else:
|
|
1144
|
+
return sorted_distances
|
|
1145
|
+
|
|
1146
|
+
def color_by_distance(
|
|
1147
|
+
self,
|
|
1148
|
+
reference_id: str,
|
|
1149
|
+
metric: str | None = None,
|
|
1150
|
+
vector_field: str = "vector",
|
|
1151
|
+
) -> None:
|
|
1152
|
+
"""Color points by distance from a reference point.
|
|
1153
|
+
|
|
1154
|
+
Updates points with a '_distance' field and sets color_field to use it.
|
|
1155
|
+
"""
|
|
1156
|
+
distances = self.compute_distances(reference_id, metric, vector_field)
|
|
1157
|
+
|
|
1158
|
+
# Update points with distance field
|
|
1159
|
+
updated_points = []
|
|
1160
|
+
for point in self.points:
|
|
1161
|
+
point_copy = dict(point)
|
|
1162
|
+
pid = point.get("id")
|
|
1163
|
+
if pid == reference_id:
|
|
1164
|
+
point_copy["_distance"] = 0.0
|
|
1165
|
+
elif pid in distances:
|
|
1166
|
+
point_copy["_distance"] = distances[pid]
|
|
1167
|
+
updated_points.append(point_copy)
|
|
1168
|
+
|
|
1169
|
+
self.points = updated_points
|
|
1170
|
+
self.color_field = "_distance"
|
|
1171
|
+
self.reference_point = reference_id
|
|
1172
|
+
|
|
1173
|
+
def show_neighbors(
|
|
1174
|
+
self,
|
|
1175
|
+
reference_id: str,
|
|
1176
|
+
k: int | None = None,
|
|
1177
|
+
threshold: float | None = None,
|
|
1178
|
+
) -> None:
|
|
1179
|
+
"""Show connections to nearest neighbors of a reference point."""
|
|
1180
|
+
self.reference_point = reference_id
|
|
1181
|
+
self.show_connections = True
|
|
1182
|
+
if k is not None:
|
|
1183
|
+
self.k_neighbors = k
|
|
1184
|
+
if threshold is not None:
|
|
1185
|
+
self.distance_threshold = threshold
|
|
1186
|
+
|
|
1187
|
+
def _get_vector(self, point: dict[str, Any], vector_field: str) -> list[float]:
|
|
1188
|
+
"""Extract vector from point, falling back to x,y,z."""
|
|
1189
|
+
if vector_field in point and point[vector_field]:
|
|
1190
|
+
vec = point[vector_field]
|
|
1191
|
+
return list(vec) if hasattr(vec, "__iter__") else [vec]
|
|
1192
|
+
return [point.get("x", 0), point.get("y", 0), point.get("z", 0)]
|
|
1193
|
+
|
|
1194
|
+
def _compute_distance(self, v1: list[float], v2: list[float], metric: str) -> float:
|
|
1195
|
+
"""Compute distance between two vectors."""
|
|
1196
|
+
import math
|
|
1197
|
+
|
|
1198
|
+
# Ensure same length
|
|
1199
|
+
n = min(len(v1), len(v2))
|
|
1200
|
+
v1, v2 = v1[:n], v2[:n]
|
|
1201
|
+
|
|
1202
|
+
if metric == "euclidean":
|
|
1203
|
+
return math.sqrt(sum((a - b) ** 2 for a, b in zip(v1, v2)))
|
|
1204
|
+
elif metric == "cosine":
|
|
1205
|
+
dot = sum(a * b for a, b in zip(v1, v2))
|
|
1206
|
+
mag1 = math.sqrt(sum(a * a for a in v1))
|
|
1207
|
+
mag2 = math.sqrt(sum(b * b for b in v2))
|
|
1208
|
+
if mag1 == 0 or mag2 == 0:
|
|
1209
|
+
return 1.0
|
|
1210
|
+
return 1 - (dot / (mag1 * mag2))
|
|
1211
|
+
elif metric == "manhattan":
|
|
1212
|
+
return sum(abs(a - b) for a, b in zip(v1, v2))
|
|
1213
|
+
elif metric == "dot_product":
|
|
1214
|
+
return -sum(a * b for a, b in zip(v1, v2))
|
|
1215
|
+
else:
|
|
1216
|
+
# Default to euclidean
|
|
1217
|
+
return math.sqrt(sum((a - b) ** 2 for a, b in zip(v1, v2)))
|
|
1218
|
+
|
|
936
1219
|
# === Export ===
|
|
937
1220
|
|
|
938
1221
|
def to_json(self) -> str:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: anywidget-vector
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Interactive vector visualization for Python notebooks using anywidget
|
|
5
5
|
Project-URL: Homepage, https://grafeo.dev/
|
|
6
6
|
Project-URL: Repository, https://github.com/GrafeoDB/anywidget-vector
|
|
@@ -264,6 +264,73 @@ widget = VectorSpace(
|
|
|
264
264
|
)
|
|
265
265
|
```
|
|
266
266
|
|
|
267
|
+
## Distance Metrics
|
|
268
|
+
|
|
269
|
+
Compute distances and visualize similarity relationships between points.
|
|
270
|
+
|
|
271
|
+
### Supported Metrics
|
|
272
|
+
|
|
273
|
+
| Metric | Description |
|
|
274
|
+
|--------|-------------|
|
|
275
|
+
| `euclidean` | Straight-line distance (L2 norm) |
|
|
276
|
+
| `cosine` | Angle-based distance (1 - cosine similarity) |
|
|
277
|
+
| `manhattan` | Sum of absolute differences (L1 norm) |
|
|
278
|
+
| `dot_product` | Negative dot product (higher = closer) |
|
|
279
|
+
|
|
280
|
+
### Color by Distance
|
|
281
|
+
|
|
282
|
+
```python
|
|
283
|
+
# Color points by distance from a reference
|
|
284
|
+
widget.color_by_distance("point_a")
|
|
285
|
+
widget.color_by_distance("point_a", metric="cosine")
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Find Neighbors
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
# Find k nearest neighbors
|
|
292
|
+
neighbors = widget.find_neighbors("point_a", k=5)
|
|
293
|
+
# Returns: [("point_b", 0.1), ("point_c", 0.2), ...]
|
|
294
|
+
|
|
295
|
+
# Find neighbors within distance threshold
|
|
296
|
+
neighbors = widget.find_neighbors("point_a", threshold=0.5)
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Show Connections
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
# Draw lines to k-nearest neighbors
|
|
303
|
+
widget.show_neighbors("point_a", k=5)
|
|
304
|
+
|
|
305
|
+
# Draw lines to all points within threshold
|
|
306
|
+
widget.show_neighbors("point_a", threshold=0.3)
|
|
307
|
+
|
|
308
|
+
# Manual connection settings
|
|
309
|
+
widget = VectorSpace(
|
|
310
|
+
points=data,
|
|
311
|
+
show_connections=True,
|
|
312
|
+
k_neighbors=3,
|
|
313
|
+
distance_metric="cosine",
|
|
314
|
+
connection_color="#00ff00",
|
|
315
|
+
connection_opacity=0.5,
|
|
316
|
+
)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Compute Distances
|
|
320
|
+
|
|
321
|
+
```python
|
|
322
|
+
# Get distances from reference to all points
|
|
323
|
+
distances = widget.compute_distances("point_a")
|
|
324
|
+
# Returns: {"point_b": 0.1, "point_c": 0.5, ...}
|
|
325
|
+
|
|
326
|
+
# Use high-dimensional vectors (not just x,y,z)
|
|
327
|
+
distances = widget.compute_distances(
|
|
328
|
+
"point_a",
|
|
329
|
+
metric="cosine",
|
|
330
|
+
vector_field="embedding" # Use full embedding vector
|
|
331
|
+
)
|
|
332
|
+
```
|
|
333
|
+
|
|
267
334
|
## Export
|
|
268
335
|
|
|
269
336
|
```python
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
anywidget_vector/__init__.py,sha256=6uLVXoFKaF4PNvMpbkOYmYEgooFVec4Bi0pGMxrfMmY,162
|
|
2
|
+
anywidget_vector/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
anywidget_vector/widget.py,sha256=6krdOLSW78YbjSO5Uyv2I4buolfLxFoTUVSBQnd9vwM,44704
|
|
4
|
+
anywidget_vector-0.2.0.dist-info/METADATA,sha256=kIgCDD5GvMZRQduAJJRwMafrRcIM3Uryt9nqixK9z1k,8942
|
|
5
|
+
anywidget_vector-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
6
|
+
anywidget_vector-0.2.0.dist-info/RECORD,,
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
anywidget_vector/__init__.py,sha256=UA1icM7Y50eVfCf8yambftuG8bxLMIjON68IVJDO4x8,162
|
|
2
|
-
anywidget_vector/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
anywidget_vector/widget.py,sha256=60AP_awiX6MUaYPIBRvfFBdFQsyqPIDjronMShQDIH0,34021
|
|
4
|
-
anywidget_vector-0.1.0.dist-info/METADATA,sha256=kVS4eGG1n0PCXNItyjPdKRTh0QpwWowXrfMv8ML7dWM,7333
|
|
5
|
-
anywidget_vector-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
6
|
-
anywidget_vector-0.1.0.dist-info/RECORD,,
|
|
File without changes
|