code-loader 1.0.209__tar.gz → 1.0.211__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.
- {code_loader-1.0.209 → code_loader-1.0.211}/PKG-INFO +3 -4
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/contract/datasetclasses.py +2 -2
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/contract/enums.py +1 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/contract/responsedataclasses.py +29 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/contract/visualizer_classes.py +58 -2
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/inner_leap_binder/leapbinder_decorators.py +4 -3
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/plot_functions/plot_functions.py +22 -1
- {code_loader-1.0.209 → code_loader-1.0.211}/pyproject.toml +1 -1
- {code_loader-1.0.209 → code_loader-1.0.211}/LICENSE +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/README.md +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/__init__.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/contract/__init__.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/contract/exceptions.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/contract/mapping.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/contract/sim_config.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/default_losses.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/default_metrics.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/__init__.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/api.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/cli_config_utils.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/client.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/epoch.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/experiment.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/experiment_context.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/types.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/utils.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/inner_leap_binder/__init__.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/inner_leap_binder/leapbinder.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/leaploader.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/leaploaderbase.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/mixpanel_tracker.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/plot_functions/__init__.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/plot_functions/visualize.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/utils.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/visualizers/__init__.py +0 -0
- {code_loader-1.0.209 → code_loader-1.0.211}/code_loader/visualizers/default_visualizers.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: code-loader
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.211
|
|
4
4
|
Summary:
|
|
5
|
+
Home-page: https://github.com/tensorleap/code-loader
|
|
5
6
|
License: MIT
|
|
6
|
-
License-File: LICENSE
|
|
7
7
|
Author: dorhar
|
|
8
8
|
Author-email: doron.harnoy@tensorleap.ai
|
|
9
9
|
Requires-Python: >=3.8,<3.13
|
|
@@ -20,7 +20,6 @@ Requires-Dist: numpy (>=2.3.2,<3.0.0) ; python_version >= "3.11" and python_vers
|
|
|
20
20
|
Requires-Dist: psutil (>=5.9.5,<6.0.0)
|
|
21
21
|
Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
|
|
22
22
|
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
|
23
|
-
Project-URL: Homepage, https://github.com/tensorleap/code-loader
|
|
24
23
|
Project-URL: Repository, https://github.com/tensorleap/code-loader
|
|
25
24
|
Description-Content-Type: text/markdown
|
|
26
25
|
|
|
@@ -8,7 +8,7 @@ import numpy.typing as npt
|
|
|
8
8
|
from code_loader.contract.enums import DataStateType, DataStateEnum, LeapDataType, ConfusionMatrixValue, \
|
|
9
9
|
MetricDirection, DatasetMetadataType, LatentSpaceReduction, CustomLatentSpaceComputedAt
|
|
10
10
|
from code_loader.contract.visualizer_classes import LeapImage, LeapText, LeapGraph, LeapHorizontalBar, \
|
|
11
|
-
LeapTextMask, LeapImageMask, LeapImageWithBBox, LeapImageWithHeatmap, LeapVideo, LeapAudio
|
|
11
|
+
LeapTextMask, LeapImageMask, LeapImageWithBBox, LeapImageWithHeatmap, LeapVideo, LeapAudio, LeapPointCloud
|
|
12
12
|
from code_loader.contract.sim_config import SimConfig
|
|
13
13
|
|
|
14
14
|
custom_latent_space_attribute = "custom_latent_space"
|
|
@@ -213,7 +213,7 @@ VisualizerCallableInterface = Union[
|
|
|
213
213
|
]
|
|
214
214
|
|
|
215
215
|
LeapData = Union[LeapImage, LeapText, LeapGraph, LeapHorizontalBar, LeapImageMask, LeapTextMask, LeapImageWithBBox,
|
|
216
|
-
LeapImageWithHeatmap, LeapVideo, LeapAudio]
|
|
216
|
+
LeapImageWithHeatmap, LeapVideo, LeapAudio, LeapPointCloud]
|
|
217
217
|
|
|
218
218
|
CustomCallableInterface = Callable[..., Any]
|
|
219
219
|
|
|
@@ -131,6 +131,35 @@ class BoundingBox:
|
|
|
131
131
|
metadata: Optional[Dict[str, Union[str, int, float]]] = None
|
|
132
132
|
|
|
133
133
|
|
|
134
|
+
@dataclass
|
|
135
|
+
class BoundingBox3D:
|
|
136
|
+
"""
|
|
137
|
+
Represents an oriented 3D bounding box in a point cloud's coordinate frame.
|
|
138
|
+
|
|
139
|
+
Attributes:
|
|
140
|
+
x, y, z (float): The center of the box.
|
|
141
|
+
width (float): Extent along the box's local y axis.
|
|
142
|
+
length (float): Extent along the box's local x axis (the heading axis).
|
|
143
|
+
height (float): Extent along the box's local z axis.
|
|
144
|
+
yaw (float): Rotation about +z in radians, counter-clockwise from +x. The +length/2 face is the front.
|
|
145
|
+
label (str): The class name of the box.
|
|
146
|
+
confidence (float): Prediction score, typically in [0, 1]; 1.0 for ground truth.
|
|
147
|
+
metadata (Optional[Dict[str, Union[str, int, float]]]): Optional extra fields shown with the box.
|
|
148
|
+
|
|
149
|
+
Corners are the local points (±length/2, ±width/2, ±height/2) rotated by yaw about z, then translated to (x, y, z).
|
|
150
|
+
"""
|
|
151
|
+
x: float
|
|
152
|
+
y: float
|
|
153
|
+
z: float
|
|
154
|
+
width: float
|
|
155
|
+
length: float
|
|
156
|
+
height: float
|
|
157
|
+
yaw: float
|
|
158
|
+
label: str
|
|
159
|
+
confidence: float = 1.0
|
|
160
|
+
metadata: Optional[Dict[str, Union[str, int, float]]] = None
|
|
161
|
+
|
|
162
|
+
|
|
134
163
|
|
|
135
164
|
@dataclass
|
|
136
165
|
class LeapAnalysisConfiguration:
|
|
@@ -5,7 +5,7 @@ import numpy.typing as npt
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
|
|
7
7
|
from code_loader.contract.enums import LeapDataType
|
|
8
|
-
from code_loader.contract.responsedataclasses import BoundingBox
|
|
8
|
+
from code_loader.contract.responsedataclasses import BoundingBox, BoundingBox3D
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class LeapValidationError(Exception):
|
|
@@ -377,6 +377,61 @@ class LeapAudio:
|
|
|
377
377
|
raise LeapValidationError(f'sample_rate must be a positive int, got {self.sample_rate}')
|
|
378
378
|
|
|
379
379
|
|
|
380
|
+
@dataclass
|
|
381
|
+
class LeapPointCloud:
|
|
382
|
+
"""
|
|
383
|
+
Visualizer representing a set of 3D points for Tensorleap: a LiDAR sweep, a depth-camera frame, a mesh's
|
|
384
|
+
vertices, or any (N, 3) point set. The UI renders it with an orbit camera; the engine stores the points as a
|
|
385
|
+
raw float32 blob.
|
|
386
|
+
|
|
387
|
+
Attributes:
|
|
388
|
+
points (npt.NDArray[np.float32]): The points, shaped [N, 3] as x, y, z in any consistent frame and unit.
|
|
389
|
+
intensity (Optional[npt.NDArray[np.float32]]): Optional per-point scalar shaped [N]: the LiDAR return
|
|
390
|
+
intensity in most formats, but any per-point value (reflectance, depth, an error) fits. The UI offers it as a
|
|
391
|
+
color mode.
|
|
392
|
+
bounding_boxes (Optional[List[BoundingBox3D]]): Optional oriented 3D boxes in the same frame as `points`.
|
|
393
|
+
An empty list is valid.
|
|
394
|
+
type (LeapDataType): The data type, default is LeapDataType.PointCloud.
|
|
395
|
+
|
|
396
|
+
Example:
|
|
397
|
+
points = (np.random.rand(1000, 3) * 50).astype(np.float32)
|
|
398
|
+
box = BoundingBox3D(x=10, y=0, z=1, width=2, length=4.5, height=1.8, yaw=0.3, label="car", confidence=0.9)
|
|
399
|
+
leap_point_cloud = LeapPointCloud(points=points, intensity=points[:, 2].copy(), bounding_boxes=[box])
|
|
400
|
+
"""
|
|
401
|
+
points: npt.NDArray[np.float32]
|
|
402
|
+
intensity: Optional[npt.NDArray[np.float32]] = None
|
|
403
|
+
bounding_boxes: Optional[List[BoundingBox3D]] = None
|
|
404
|
+
type: LeapDataType = LeapDataType.PointCloud
|
|
405
|
+
|
|
406
|
+
def __post_init__(self) -> None:
|
|
407
|
+
validate_type(self.type, LeapDataType.PointCloud)
|
|
408
|
+
validate_type(type(self.points), np.ndarray)
|
|
409
|
+
validate_type(self.points.dtype, np.float32)
|
|
410
|
+
validate_type(len(self.points.shape), 2, 'Point cloud points must be of shape 2 [N, 3]')
|
|
411
|
+
if self.points.shape[1] != 3 or self.points.shape[0] < 1:
|
|
412
|
+
raise LeapValidationError(
|
|
413
|
+
f'Point cloud points must be of shape [N, 3] with N >= 1, got {self.points.shape}')
|
|
414
|
+
if not np.isfinite(self.points).all():
|
|
415
|
+
raise LeapValidationError('Point cloud points must be finite (no NaN/Inf)')
|
|
416
|
+
if self.intensity is not None:
|
|
417
|
+
validate_type(type(self.intensity), np.ndarray)
|
|
418
|
+
validate_type(self.intensity.dtype, np.float32)
|
|
419
|
+
if self.intensity.shape != (self.points.shape[0],):
|
|
420
|
+
raise LeapValidationError(
|
|
421
|
+
f'Point cloud intensity shape {self.intensity.shape} must be ({self.points.shape[0]},)')
|
|
422
|
+
if not np.isfinite(self.intensity).all():
|
|
423
|
+
raise LeapValidationError('Point cloud intensity must be finite (no NaN/Inf)')
|
|
424
|
+
if self.bounding_boxes is not None:
|
|
425
|
+
validate_type(type(self.bounding_boxes), list)
|
|
426
|
+
for box in self.bounding_boxes:
|
|
427
|
+
validate_type(type(box), BoundingBox3D)
|
|
428
|
+
numbers = (box.x, box.y, box.z, box.width, box.length, box.height, box.yaw, box.confidence)
|
|
429
|
+
if not all(np.isfinite(float(v)) for v in numbers):
|
|
430
|
+
raise LeapValidationError(f'BoundingBox3D "{box.label}" has a non-finite field')
|
|
431
|
+
if min(box.width, box.length, box.height) <= 0:
|
|
432
|
+
raise LeapValidationError(f'BoundingBox3D "{box.label}" extents must be positive')
|
|
433
|
+
|
|
434
|
+
|
|
380
435
|
map_leap_data_type_to_visualizer_class = {
|
|
381
436
|
LeapDataType.Image.value: LeapImage,
|
|
382
437
|
LeapDataType.Graph.value: LeapGraph,
|
|
@@ -387,5 +442,6 @@ map_leap_data_type_to_visualizer_class = {
|
|
|
387
442
|
LeapDataType.TextMask.value: LeapTextMask,
|
|
388
443
|
LeapDataType.ImageWithBBox.value: LeapImageWithBBox,
|
|
389
444
|
LeapDataType.ImageWithHeatmap.value: LeapImageWithHeatmap,
|
|
390
|
-
LeapDataType.Audio.value: LeapAudio
|
|
445
|
+
LeapDataType.Audio.value: LeapAudio,
|
|
446
|
+
LeapDataType.PointCloud.value: LeapPointCloud,
|
|
391
447
|
}
|
{code_loader-1.0.209 → code_loader-1.0.211}/code_loader/inner_leap_binder/leapbinder_decorators.py
RENAMED
|
@@ -34,8 +34,8 @@ from code_loader.contract.enums import MetricDirection, LeapDataType, DatasetMet
|
|
|
34
34
|
from code_loader import leap_binder, LeapLoader
|
|
35
35
|
from code_loader.contract.mapping import NodeMapping, NodeMappingType, NodeConnection
|
|
36
36
|
from code_loader.contract.visualizer_classes import LeapImage, LeapImageMask, LeapTextMask, LeapText, LeapGraph, \
|
|
37
|
-
LeapHorizontalBar, LeapImageWithBBox, LeapImageWithHeatmap, LeapVideo, LeapAudio,
|
|
38
|
-
map_leap_data_type_to_visualizer_class
|
|
37
|
+
LeapHorizontalBar, LeapImageWithBBox, LeapImageWithHeatmap, LeapVideo, LeapAudio, LeapPointCloud, \
|
|
38
|
+
LeapValidationError, map_leap_data_type_to_visualizer_class
|
|
39
39
|
from code_loader.inner_leap_binder.leapbinder import mapping_runtime_mode_env_var_mame, \
|
|
40
40
|
_reject_stringized_sample_preprocess_response
|
|
41
41
|
from code_loader.mixpanel_tracker import clear_integration_events, AnalyticsEvent, emit_integration_event_once
|
|
@@ -1593,7 +1593,8 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
1593
1593
|
LeapDataType.ImageWithBBox: LeapImageWithBBox,
|
|
1594
1594
|
LeapDataType.ImageWithHeatmap: LeapImageWithHeatmap,
|
|
1595
1595
|
LeapDataType.Video: LeapVideo,
|
|
1596
|
-
LeapDataType.Audio: LeapAudio
|
|
1596
|
+
LeapDataType.Audio: LeapAudio,
|
|
1597
|
+
LeapDataType.PointCloud: LeapPointCloud
|
|
1597
1598
|
}
|
|
1598
1599
|
validate_output_structure(result, func_name=user_function.__name__,
|
|
1599
1600
|
expected_type_name=result_type_map[visualizer_type])
|
|
@@ -20,7 +20,7 @@ from textwrap import wrap
|
|
|
20
20
|
import math
|
|
21
21
|
|
|
22
22
|
from code_loader.contract.visualizer_classes import LeapImage, LeapImageWithBBox, LeapGraph, LeapText, \
|
|
23
|
-
LeapHorizontalBar, LeapImageMask, LeapTextMask, LeapImageWithHeatmap, LeapVideo
|
|
23
|
+
LeapHorizontalBar, LeapImageMask, LeapTextMask, LeapImageWithHeatmap, LeapVideo, LeapPointCloud
|
|
24
24
|
from code_loader.utils import rescale_min_max
|
|
25
25
|
|
|
26
26
|
|
|
@@ -464,6 +464,26 @@ def plot_image_with_heatmap(leap_data: LeapImageWithHeatmap, title: str) -> None
|
|
|
464
464
|
|
|
465
465
|
|
|
466
466
|
|
|
467
|
+
@run_only_on_non_mapping_mode()
|
|
468
|
+
def plot_point_cloud(leap_data: LeapPointCloud, title: str) -> None:
|
|
469
|
+
"""Bird's-eye view (x right, y up, equal aspect): points colored by height, box footprints as polylines."""
|
|
470
|
+
points = leap_data.points
|
|
471
|
+
fig, ax = plt.subplots(figsize=(7, 7))
|
|
472
|
+
fig.patch.set_facecolor('black')
|
|
473
|
+
ax.set_facecolor('black')
|
|
474
|
+
ax.scatter(points[:, 0], points[:, 1], s=1, c=points[:, 2], cmap='viridis')
|
|
475
|
+
for box in leap_data.bounding_boxes or []:
|
|
476
|
+
c, s = np.cos(box.yaw), np.sin(box.yaw)
|
|
477
|
+
local = np.array([[1, 1], [1, -1], [-1, -1], [-1, 1], [1, 1]], dtype=np.float64) * [box.length / 2, box.width / 2]
|
|
478
|
+
corners = local @ np.array([[c, -s], [s, c]]).T + [box.x, box.y]
|
|
479
|
+
ax.plot(corners[:, 0], corners[:, 1], linewidth=1.5, color='orange')
|
|
480
|
+
ax.text(box.x, box.y, f'{box.label} {box.confidence:.2f}', color='orange', fontsize=6)
|
|
481
|
+
ax.set_aspect('equal')
|
|
482
|
+
ax.set_title(f'{title} ({points.shape[0]} points)', color='white')
|
|
483
|
+
ax.tick_params(colors='white')
|
|
484
|
+
plt.show()
|
|
485
|
+
|
|
486
|
+
|
|
467
487
|
plot_switch = {
|
|
468
488
|
LeapDataType.Image: plot_image,
|
|
469
489
|
LeapDataType.Text: plot_text_with_heatmap,
|
|
@@ -474,4 +494,5 @@ plot_switch = {
|
|
|
474
494
|
LeapDataType.ImageWithHeatmap: plot_image_with_heatmap,
|
|
475
495
|
LeapDataType.ImageWithBBox: plot_image_with_b_box,
|
|
476
496
|
LeapDataType.Video: plot_video,
|
|
497
|
+
LeapDataType.PointCloud: plot_point_cloud,
|
|
477
498
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/experiment_context.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.209 → code_loader-1.0.211}/code_loader/experiment_api/workingspace_config_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|