code-loader 1.0.198__tar.gz → 1.0.200__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.198 → code_loader-1.0.200}/PKG-INFO +1 -1
- code_loader-1.0.200/code_loader/contract/__pycache__/__init__.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/contract/__pycache__/datasetclasses.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/contract/__pycache__/enums.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/contract/__pycache__/exceptions.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/contract/__pycache__/mapping.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/contract/__pycache__/responsedataclasses.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/contract/__pycache__/sim_config.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/contract/__pycache__/visualizer_classes.cpython-39.pyc +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/contract/datasetclasses.py +6 -6
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/contract/enums.py +1 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/contract/visualizer_classes.py +43 -1
- code_loader-1.0.200/code_loader/experiment_api/__pycache__/__init__.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/experiment_api/__pycache__/api.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/experiment_api/__pycache__/cli_config_utils.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/experiment_api/__pycache__/client.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/experiment_api/__pycache__/epoch.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/experiment_api/__pycache__/experiment.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/experiment_api/__pycache__/experiment_context.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/experiment_api/__pycache__/types.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/experiment_api/__pycache__/utils.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/experiment_api/__pycache__/workingspace_config_utils.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/inner_leap_binder/__pycache__/__init__.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/inner_leap_binder/__pycache__/leapbinder.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/inner_leap_binder/__pycache__/leapbinder_decorators.cpython-39.pyc +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/inner_leap_binder/leapbinder.py +6 -42
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/inner_leap_binder/leapbinder_decorators.py +7 -13
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/leaploader.py +28 -55
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/leaploaderbase.py +0 -8
- code_loader-1.0.200/code_loader/visualizers/__pycache__/__init__.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/visualizers/__pycache__/default_visualizers.cpython-39.pyc +0 -0
- code_loader-1.0.200/code_loader/visualizers/default_visualizers.py +156 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/pyproject.toml +1 -1
- code_loader-1.0.198/code_loader/visualizers/default_visualizers.py +0 -85
- {code_loader-1.0.198 → code_loader-1.0.200}/LICENSE +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/README.md +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/__init__.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/contract/__init__.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/contract/exceptions.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/contract/mapping.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/contract/responsedataclasses.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/contract/sim_config.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/default_losses.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/default_metrics.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/__init__.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/api.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/cli_config_utils.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/client.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/epoch.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/experiment.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/experiment_context.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/types.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/utils.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/inner_leap_binder/__init__.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/mixpanel_tracker.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/plot_functions/__init__.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/plot_functions/plot_functions.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/plot_functions/visualize.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/utils.py +0 -0
- {code_loader-1.0.198 → code_loader-1.0.200}/code_loader/visualizers/__init__.py +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
|
10
10
|
from code_loader.contract.visualizer_classes import LeapImage, LeapText, LeapGraph, LeapHorizontalBar, \
|
|
11
|
-
LeapTextMask, LeapImageMask, LeapImageWithBBox, LeapImageWithHeatmap, LeapVideo
|
|
11
|
+
LeapTextMask, LeapImageMask, LeapImageWithBBox, LeapImageWithHeatmap, LeapVideo, LeapAudio
|
|
12
12
|
from code_loader.contract.sim_config import SimConfig
|
|
13
13
|
|
|
14
14
|
custom_latent_space_attribute = "custom_latent_space"
|
|
@@ -194,11 +194,12 @@ VisualizerCallableInterface = Union[
|
|
|
194
194
|
Callable[..., LeapImageMask],
|
|
195
195
|
Callable[..., LeapTextMask],
|
|
196
196
|
Callable[..., LeapImageWithBBox],
|
|
197
|
-
Callable[..., LeapImageWithHeatmap]
|
|
197
|
+
Callable[..., LeapImageWithHeatmap],
|
|
198
|
+
Callable[..., LeapAudio]
|
|
198
199
|
]
|
|
199
200
|
|
|
200
201
|
LeapData = Union[LeapImage, LeapText, LeapGraph, LeapHorizontalBar, LeapImageMask, LeapTextMask, LeapImageWithBBox,
|
|
201
|
-
LeapImageWithHeatmap, LeapVideo]
|
|
202
|
+
LeapImageWithHeatmap, LeapVideo, LeapAudio]
|
|
202
203
|
|
|
203
204
|
CustomCallableInterface = Callable[..., Any]
|
|
204
205
|
|
|
@@ -308,7 +309,6 @@ class MetadataHandler:
|
|
|
308
309
|
class CustomLatentSpaceHandler:
|
|
309
310
|
function: SectionCallableInterface
|
|
310
311
|
name: str = 'custom_latent_space'
|
|
311
|
-
use_ls_for_analysis: bool = False
|
|
312
312
|
|
|
313
313
|
|
|
314
314
|
# How a chain's latent-space vectors are derived from its per-step forward passes.
|
|
@@ -391,7 +391,7 @@ class DatasetIntegrationSetup:
|
|
|
391
391
|
metrics: List[MetricHandler] = field(default_factory=list)
|
|
392
392
|
instance_metrics: List[InstanceMetricHandler] = field(default_factory=list)
|
|
393
393
|
custom_layers: Dict[str, CustomLayerHandler] = field(default_factory=dict)
|
|
394
|
-
|
|
394
|
+
custom_latent_space: Optional[CustomLatentSpaceHandler] = None
|
|
395
395
|
simulations: List[SimulationHandler] = field(default_factory=list)
|
|
396
396
|
autoregressive_step: Optional[AutoregressiveStepHandler] = None
|
|
397
397
|
autoregressive_metrics: List[AutoregressiveMetricHandler] = field(default_factory=list)
|
|
@@ -407,6 +407,6 @@ class DatasetSample:
|
|
|
407
407
|
metadata_is_none: Dict[str, bool]
|
|
408
408
|
index: Union[int, str]
|
|
409
409
|
state: DataStateEnum
|
|
410
|
-
|
|
410
|
+
custom_latent_space: Optional[npt.NDArray[np.float32]] = None
|
|
411
411
|
instance_masks: Optional[Dict[str, ElementInstance]] = None
|
|
412
412
|
|
|
@@ -343,6 +343,47 @@ class LeapImageWithHeatmap:
|
|
|
343
343
|
'Number of heatmaps and labels must be equal')
|
|
344
344
|
|
|
345
345
|
|
|
346
|
+
@dataclass
|
|
347
|
+
class LeapAudio:
|
|
348
|
+
"""
|
|
349
|
+
Visualizer representing a playable audio sample for Tensorleap.
|
|
350
|
+
|
|
351
|
+
The user plays the sample in the right panel while a playhead tick runs
|
|
352
|
+
through `visual` — either a spectrogram (a LeapImage) or a time-series
|
|
353
|
+
waveform (a LeapGraph). Build one with `default_audio_visualizer`.
|
|
354
|
+
|
|
355
|
+
Attributes:
|
|
356
|
+
audio (npt.NDArray): Mono waveform samples, shaped [N]. Multi-channel input
|
|
357
|
+
should be mixed down before constructing LeapAudio.
|
|
358
|
+
sample_rate (int): Samples per second — needed to encode the clip and to map
|
|
359
|
+
the playhead position to time.
|
|
360
|
+
visual (Union[LeapImage, LeapGraph]): The thing you look at.
|
|
361
|
+
x_range (Optional[Tuple[float, float]]): Time extent (in seconds) that the
|
|
362
|
+
visual's horizontal axis spans, used to align the tick. Defaults to
|
|
363
|
+
(0, N / sample_rate).
|
|
364
|
+
type (LeapDataType): The data type, default is LeapDataType.Audio.
|
|
365
|
+
"""
|
|
366
|
+
audio: npt.NDArray
|
|
367
|
+
sample_rate: int
|
|
368
|
+
visual: Union[LeapImage, LeapGraph]
|
|
369
|
+
x_range: Optional[Tuple[float, float]] = None
|
|
370
|
+
type: LeapDataType = LeapDataType.Audio
|
|
371
|
+
|
|
372
|
+
def __post_init__(self) -> None:
|
|
373
|
+
validate_type(self.type, LeapDataType.Audio)
|
|
374
|
+
validate_type(type(self.audio), np.ndarray)
|
|
375
|
+
validate_type(len(self.audio.shape), 1, 'Audio must be mono, of shape 1 [N]')
|
|
376
|
+
validate_type(type(self.visual), [LeapImage, LeapGraph],
|
|
377
|
+
'Audio visual must be a LeapImage (spectrogram) or LeapGraph (waveform)')
|
|
378
|
+
if not isinstance(self.sample_rate, int) or self.sample_rate <= 0:
|
|
379
|
+
raise LeapValidationError(f'sample_rate must be a positive int, got {self.sample_rate}')
|
|
380
|
+
if self.x_range is not None:
|
|
381
|
+
if len(self.x_range) != 2:
|
|
382
|
+
raise LeapValidationError('x_range must be a tuple of length 2')
|
|
383
|
+
validate_type(type(self.x_range[0]), [float, int], 'x_range must be a tuple of floats or integers')
|
|
384
|
+
validate_type(type(self.x_range[1]), [float, int], 'x_range must be a tuple of floats or integers')
|
|
385
|
+
|
|
386
|
+
|
|
346
387
|
map_leap_data_type_to_visualizer_class = {
|
|
347
388
|
LeapDataType.Image.value: LeapImage,
|
|
348
389
|
LeapDataType.Graph.value: LeapGraph,
|
|
@@ -352,5 +393,6 @@ map_leap_data_type_to_visualizer_class = {
|
|
|
352
393
|
LeapDataType.ImageMask.value: LeapImageMask,
|
|
353
394
|
LeapDataType.TextMask.value: LeapTextMask,
|
|
354
395
|
LeapDataType.ImageWithBBox.value: LeapImageWithBBox,
|
|
355
|
-
LeapDataType.ImageWithHeatmap.value: LeapImageWithHeatmap
|
|
396
|
+
LeapDataType.ImageWithHeatmap.value: LeapImageWithHeatmap,
|
|
397
|
+
LeapDataType.Audio.value: LeapAudio
|
|
356
398
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
code_loader-1.0.200/code_loader/experiment_api/__pycache__/workingspace_config_utils.cpython-39.pyc
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
code_loader-1.0.200/code_loader/inner_leap_binder/__pycache__/leapbinder_decorators.cpython-39.pyc
ADDED
|
Binary file
|
|
@@ -536,54 +536,18 @@ class LeapBinder:
|
|
|
536
536
|
"""
|
|
537
537
|
self.setup_container.metadata.append(MetadataHandler(name, function, metadata_type))
|
|
538
538
|
|
|
539
|
-
def set_custom_latent_space(self, function: SectionCallableInterface
|
|
540
|
-
name: Optional[str] = None,
|
|
541
|
-
use_ls_for_analysis: bool = False) -> None:
|
|
539
|
+
def set_custom_latent_space(self, function: SectionCallableInterface) -> None:
|
|
542
540
|
"""
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
Multiple custom latent spaces may be registered as long as each has a
|
|
546
|
-
unique name. They are stored name-keyed (insertion order preserved), so a
|
|
547
|
-
later registration no longer overrides an earlier one.
|
|
541
|
+
Set a custom latent space function.
|
|
548
542
|
|
|
549
543
|
Args:
|
|
550
|
-
function (SectionCallableInterface): The
|
|
544
|
+
function (SectionCallableInterface): The metadata handler function.
|
|
551
545
|
This function receives:
|
|
552
546
|
subset (PreprocessResponse): The subset of the data.
|
|
553
547
|
index (int): The index of the sample within the subset.
|
|
554
|
-
This function should
|
|
555
|
-
space vec of the sample.
|
|
556
|
-
name (Optional[str]): Unique name for this custom latent space. Defaults to
|
|
557
|
-
the reserved single-LS name for backward compatibility.
|
|
558
|
-
use_ls_for_analysis (bool): When True, the engine uses this custom latent
|
|
559
|
-
space for the Out-Of-Distribution and Domain-Gap insights instead of the
|
|
560
|
-
built-in defaults. At most one registered custom latent space may set this;
|
|
561
|
-
registering a second one with the flag raises.
|
|
548
|
+
This function should numpy float32 array contains the latent space vec of the sample.
|
|
562
549
|
"""
|
|
563
|
-
|
|
564
|
-
name = custom_latent_space_attribute
|
|
565
|
-
if name in self.setup_container.custom_latent_spaces:
|
|
566
|
-
raise Exception(
|
|
567
|
-
f"A custom latent space named '{name}' is already registered. Each "
|
|
568
|
-
f"@tensorleap_custom_latent_space must have a unique name "
|
|
569
|
-
f"(pass name='...' to distinguish them)."
|
|
570
|
-
)
|
|
571
|
-
if use_ls_for_analysis:
|
|
572
|
-
already_flagged = [
|
|
573
|
-
existing_name
|
|
574
|
-
for existing_name, handler in self.setup_container.custom_latent_spaces.items()
|
|
575
|
-
if handler.use_ls_for_analysis
|
|
576
|
-
]
|
|
577
|
-
if already_flagged:
|
|
578
|
-
raise Exception(
|
|
579
|
-
f"use_ls_for_analysis=True is already set on custom latent space "
|
|
580
|
-
f"'{already_flagged[0]}'. Only one custom latent space may set "
|
|
581
|
-
f"use_ls_for_analysis=True (it selects the latent space used for the "
|
|
582
|
-
f"Out-Of-Distribution and Domain-Gap insights). Set it on '{name}' "
|
|
583
|
-
f"or '{already_flagged[0]}', not both."
|
|
584
|
-
)
|
|
585
|
-
self.setup_container.custom_latent_spaces[name] = CustomLatentSpaceHandler(
|
|
586
|
-
function, name, use_ls_for_analysis)
|
|
550
|
+
self.setup_container.custom_latent_space = CustomLatentSpaceHandler(function)
|
|
587
551
|
|
|
588
552
|
def set_autoregressive_step(self, function: AutoregressiveStepCallableInterface,
|
|
589
553
|
latent_space_aggregation: str = 'last_step') -> None:
|
|
@@ -994,7 +958,7 @@ class LeapBinder:
|
|
|
994
958
|
"Element instances are not supported together with tensorleap_autoregressive_step: "
|
|
995
959
|
"instance generation masks the sample's encoded inputs, which do not exist in an "
|
|
996
960
|
"autoregressive integration. Remove the instance encoders or the autoregressive hook.")
|
|
997
|
-
if self.setup_container.
|
|
961
|
+
if self.setup_container.custom_latent_space is not None:
|
|
998
962
|
raise Exception(
|
|
999
963
|
"tensorleap_custom_latent_space is not supported together with "
|
|
1000
964
|
"tensorleap_autoregressive_step: the custom latent space function only sees "
|
{code_loader-1.0.198 → code_loader-1.0.200}/code_loader/inner_leap_binder/leapbinder_decorators.py
RENAMED
|
@@ -29,7 +29,7 @@ from code_loader.contract.enums import MetricDirection, LeapDataType, DatasetMet
|
|
|
29
29
|
from code_loader import leap_binder, LeapLoader
|
|
30
30
|
from code_loader.contract.mapping import NodeMapping, NodeMappingType, NodeConnection
|
|
31
31
|
from code_loader.contract.visualizer_classes import LeapImage, LeapImageMask, LeapTextMask, LeapText, LeapGraph, \
|
|
32
|
-
LeapHorizontalBar, LeapImageWithBBox, LeapImageWithHeatmap, LeapVideo, LeapValidationError, \
|
|
32
|
+
LeapHorizontalBar, LeapImageWithBBox, LeapImageWithHeatmap, LeapVideo, LeapAudio, LeapValidationError, \
|
|
33
33
|
map_leap_data_type_to_visualizer_class
|
|
34
34
|
from code_loader.inner_leap_binder.leapbinder import mapping_runtime_mode_env_var_mame
|
|
35
35
|
from code_loader.mixpanel_tracker import clear_integration_events, AnalyticsEvent, emit_integration_event_once
|
|
@@ -1543,7 +1543,8 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
1543
1543
|
LeapDataType.HorizontalBar: LeapHorizontalBar,
|
|
1544
1544
|
LeapDataType.ImageWithBBox: LeapImageWithBBox,
|
|
1545
1545
|
LeapDataType.ImageWithHeatmap: LeapImageWithHeatmap,
|
|
1546
|
-
LeapDataType.Video: LeapVideo
|
|
1546
|
+
LeapDataType.Video: LeapVideo,
|
|
1547
|
+
LeapDataType.Audio: LeapAudio
|
|
1547
1548
|
}
|
|
1548
1549
|
validate_output_structure(result, func_name=user_function.__name__,
|
|
1549
1550
|
expected_type_name=result_type_map[visualizer_type])
|
|
@@ -1702,14 +1703,8 @@ def tensorleap_metadata(
|
|
|
1702
1703
|
return decorating_function
|
|
1703
1704
|
|
|
1704
1705
|
|
|
1705
|
-
def tensorleap_custom_latent_space(
|
|
1706
|
-
assert isinstance(use_ls_for_analysis, bool), \
|
|
1707
|
-
("tensorleap_custom_latent_space validation failed: use_ls_for_analysis must be a bool. "
|
|
1708
|
-
f"Got {type(use_ls_for_analysis)}.")
|
|
1709
|
-
|
|
1706
|
+
def tensorleap_custom_latent_space():
|
|
1710
1707
|
def decorating_function(user_function: SectionCallableInterface):
|
|
1711
|
-
ls_name = name if name is not None else user_function.__name__
|
|
1712
|
-
|
|
1713
1708
|
def _validate_input_args(sample_id: Union[int, str, list], preprocess_response: PreprocessResponse):
|
|
1714
1709
|
_validate_id_or_group(sample_id, preprocess_response, 'tensorleap_custom_latent_space')
|
|
1715
1710
|
|
|
@@ -1720,9 +1715,9 @@ def tensorleap_custom_latent_space(name: Optional[str] = None, use_ls_for_analys
|
|
|
1720
1715
|
if single_result.ndim > 1:
|
|
1721
1716
|
flat_dim = int(np.prod(single_result.shape))
|
|
1722
1717
|
store_general_warning(
|
|
1723
|
-
key=("tensorleap_custom_latent_space_flatten",
|
|
1718
|
+
key=("tensorleap_custom_latent_space_flatten", tuple(single_result.shape)),
|
|
1724
1719
|
message=(
|
|
1725
|
-
f"tensorleap_custom_latent_space
|
|
1720
|
+
f"tensorleap_custom_latent_space returned per-sample shape {tuple(single_result.shape)} "
|
|
1726
1721
|
f"(ndim={single_result.ndim}). Tensorleap assumes per-sample shape (d, ...) and will "
|
|
1727
1722
|
f"flatten to ({flat_dim},) before downstream visualization and clustering. "
|
|
1728
1723
|
f"If you want a different aggregation (e.g. global average pooling), do it "
|
|
@@ -1765,8 +1760,7 @@ def tensorleap_custom_latent_space(name: Optional[str] = None, use_ls_for_analys
|
|
|
1765
1760
|
|
|
1766
1761
|
return result
|
|
1767
1762
|
|
|
1768
|
-
leap_binder.set_custom_latent_space(inner_without_validate
|
|
1769
|
-
use_ls_for_analysis=use_ls_for_analysis)
|
|
1763
|
+
leap_binder.set_custom_latent_space(inner_without_validate)
|
|
1770
1764
|
|
|
1771
1765
|
def inner(sample_id, preprocess_response):
|
|
1772
1766
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
@@ -283,7 +283,17 @@ class LeapLoader(LeapLoaderBase):
|
|
|
283
283
|
|
|
284
284
|
metadata, metadata_is_none = self.get_metadata(state, sample_id)
|
|
285
285
|
|
|
286
|
-
|
|
286
|
+
custom_latent_space = None
|
|
287
|
+
if global_leap_binder.setup_container.custom_latent_space is not None:
|
|
288
|
+
latent_fn = global_leap_binder.setup_container.custom_latent_space.function
|
|
289
|
+
preprocess_state = preprocess_result[state]
|
|
290
|
+
if preprocess_state.is_grouped:
|
|
291
|
+
# Single-sample fetch: encode this sample only, not the whole group (same
|
|
292
|
+
# memory rationale as _get_dataset_handlers; see grouped-fetch-oom-bug.md).
|
|
293
|
+
self._locate_group(preprocess_state, sample_id) # validates group membership
|
|
294
|
+
custom_latent_space = self._to_grouped_list(latent_fn([sample_id], preprocess_state))[0]
|
|
295
|
+
else:
|
|
296
|
+
custom_latent_space = latent_fn(sample_id, preprocess_state)
|
|
287
297
|
instance_mask = self._get_instances_masks(state, sample_id, instance_id)
|
|
288
298
|
sample = DatasetSample(inputs=self._get_inputs(state, sample_id),
|
|
289
299
|
gt=None if state == DataStateEnum.unlabeled else self._get_gt(state, sample_id),
|
|
@@ -291,7 +301,7 @@ class LeapLoader(LeapLoaderBase):
|
|
|
291
301
|
metadata_is_none=metadata_is_none,
|
|
292
302
|
index=sample_id,
|
|
293
303
|
state=state,
|
|
294
|
-
|
|
304
|
+
custom_latent_space=custom_latent_space,
|
|
295
305
|
instance_masks=instance_mask)
|
|
296
306
|
return sample
|
|
297
307
|
|
|
@@ -322,7 +332,11 @@ class LeapLoader(LeapLoaderBase):
|
|
|
322
332
|
handler.name, handler_result
|
|
323
333
|
)
|
|
324
334
|
|
|
325
|
-
|
|
335
|
+
custom_latent_space = None
|
|
336
|
+
if global_leap_binder.setup_container.custom_latent_space is not None:
|
|
337
|
+
custom_latent_space = global_leap_binder.setup_container.custom_latent_space.function(
|
|
338
|
+
original_sample_id, preprocess
|
|
339
|
+
)
|
|
326
340
|
|
|
327
341
|
return DatasetSample(
|
|
328
342
|
inputs=inputs,
|
|
@@ -331,7 +345,7 @@ class LeapLoader(LeapLoaderBase):
|
|
|
331
345
|
metadata_is_none=metadata_is_none,
|
|
332
346
|
index=synthetic_index,
|
|
333
347
|
state=DataStateEnum.additional,
|
|
334
|
-
|
|
348
|
+
custom_latent_space=custom_latent_space,
|
|
335
349
|
instance_masks=None,
|
|
336
350
|
)
|
|
337
351
|
|
|
@@ -1100,20 +1114,17 @@ class LeapLoader(LeapLoaderBase):
|
|
|
1100
1114
|
metadata[handler.name] = [v for v, _ in converted]
|
|
1101
1115
|
metadata_is_none[handler.name] = [is_none for _, is_none in converted]
|
|
1102
1116
|
|
|
1103
|
-
#
|
|
1104
|
-
#
|
|
1105
|
-
#
|
|
1106
|
-
#
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
name: self._to_grouped_list(handler.function(group_ids, preprocess_state))
|
|
1112
|
-
for name, handler in latent_handlers.items()
|
|
1113
|
-
}
|
|
1117
|
+
# custom_latent_space is group-aware like the input/GT encoders: hand it the whole group in a
|
|
1118
|
+
# single call so a file-backed latent fn loads the file once, and normalize to (B, d). This
|
|
1119
|
+
# keeps the mandatory group path non-lossy. instance_masks stay None here: they are a
|
|
1120
|
+
# per-(sample, instance) concern that needs an instance_id the group fetch does not carry.
|
|
1121
|
+
custom_latent_space = None
|
|
1122
|
+
if global_leap_binder.setup_container.custom_latent_space is not None:
|
|
1123
|
+
latent_fn = global_leap_binder.setup_container.custom_latent_space.function
|
|
1124
|
+
custom_latent_space = self._to_grouped_list(latent_fn(group_ids, preprocess_state))
|
|
1114
1125
|
|
|
1115
1126
|
return DatasetSample(inputs=inputs, gt=gt, metadata=metadata, metadata_is_none=metadata_is_none,
|
|
1116
|
-
index=list(group_ids), state=state,
|
|
1127
|
+
index=list(group_ids), state=state, custom_latent_space=custom_latent_space,
|
|
1117
1128
|
instance_masks=None)
|
|
1118
1129
|
|
|
1119
1130
|
def _get_inputs(self, state: DataStateEnum, sample_id: Union[int, str]) -> Dict[str, npt.NDArray[np.float32]]:
|
|
@@ -1326,48 +1337,10 @@ class LeapLoader(LeapLoaderBase):
|
|
|
1326
1337
|
|
|
1327
1338
|
return id_type
|
|
1328
1339
|
|
|
1329
|
-
def _get_custom_latent_spaces(
|
|
1330
|
-
self,
|
|
1331
|
-
sample_id: Union[int, str],
|
|
1332
|
-
preprocess: "PreprocessResponse") -> Optional[Dict[str, npt.NDArray[np.float32]]]:
|
|
1333
|
-
handlers = global_leap_binder.setup_container.custom_latent_spaces
|
|
1334
|
-
if not handlers:
|
|
1335
|
-
return None
|
|
1336
|
-
if preprocess.is_grouped:
|
|
1337
|
-
# Single-sample fetch: encode this sample only, not the whole group (same
|
|
1338
|
-
# memory rationale as _get_dataset_handlers; see grouped-fetch-oom-bug.md).
|
|
1339
|
-
self._locate_group(preprocess, sample_id) # validates group membership
|
|
1340
|
-
return {name: self._to_grouped_list(handler.function([sample_id], preprocess))[0]
|
|
1341
|
-
for name, handler in handlers.items()}
|
|
1342
|
-
return {name: handler.function(sample_id, preprocess) for name, handler in handlers.items()}
|
|
1343
|
-
|
|
1344
1340
|
@lru_cache()
|
|
1345
1341
|
def has_custom_latent_space_decorator(self) -> bool:
|
|
1346
1342
|
self.exec_script()
|
|
1347
|
-
return
|
|
1348
|
-
|
|
1349
|
-
@lru_cache()
|
|
1350
|
-
def get_custom_latent_space_names(self) -> Tuple[str, ...]:
|
|
1351
|
-
"""Ordered names of all registered custom latent spaces.
|
|
1352
|
-
|
|
1353
|
-
Registration order is the canonical index mapping consumed by the engine
|
|
1354
|
-
(name i -> user_custom_i). Returns a tuple so the lru_cache value is hashable.
|
|
1355
|
-
"""
|
|
1356
|
-
self.exec_script()
|
|
1357
|
-
return tuple(global_leap_binder.setup_container.custom_latent_spaces.keys())
|
|
1358
|
-
|
|
1359
|
-
@lru_cache()
|
|
1360
|
-
def get_custom_latent_space_for_analysis(self) -> Optional[str]:
|
|
1361
|
-
"""Name of the custom latent space flagged with use_ls_for_analysis=True, if any.
|
|
1362
|
-
|
|
1363
|
-
The engine uses this latent space for the Out-Of-Distribution and Domain-Gap
|
|
1364
|
-
insights instead of the built-in defaults. Returns None when no custom latent
|
|
1365
|
-
space set the flag. At most one is flagged (enforced at registration time)."""
|
|
1366
|
-
self.exec_script()
|
|
1367
|
-
for name, handler in global_leap_binder.setup_container.custom_latent_spaces.items():
|
|
1368
|
-
if handler.use_ls_for_analysis:
|
|
1369
|
-
return name
|
|
1370
|
-
return None
|
|
1343
|
+
return global_leap_binder.setup_container.custom_latent_space is not None
|
|
1371
1344
|
|
|
1372
1345
|
@lru_cache()
|
|
1373
1346
|
def has_autoregressive_step(self) -> bool:
|
|
@@ -218,14 +218,6 @@ class LeapLoaderBase:
|
|
|
218
218
|
raise NotImplementedError(f'{type(self).__name__} does not implement '
|
|
219
219
|
'autoregressive_visualizer_by_name.')
|
|
220
220
|
|
|
221
|
-
@abstractmethod
|
|
222
|
-
def get_custom_latent_space_names(self) -> Tuple[str, ...]:
|
|
223
|
-
pass
|
|
224
|
-
|
|
225
|
-
@abstractmethod
|
|
226
|
-
def get_custom_latent_space_for_analysis(self) -> Optional[str]:
|
|
227
|
-
pass
|
|
228
|
-
|
|
229
221
|
@abstractmethod
|
|
230
222
|
def get_heatmap_visualizer_raw_vis_input_arg_name(self, visualizer_name: str) -> Optional[str]:
|
|
231
223
|
pass
|
|
Binary file
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import numpy.typing as npt
|
|
6
|
+
|
|
7
|
+
from code_loader.contract.visualizer_classes import LeapImage, LeapGraph, LeapHorizontalBar, LeapText, \
|
|
8
|
+
LeapImageMask, LeapTextMask, LeapVideo, LeapAudio
|
|
9
|
+
from code_loader.utils import rescale_min_max
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DefaultVisualizer(Enum):
|
|
13
|
+
Image = 'Image'
|
|
14
|
+
Video = 'Video'
|
|
15
|
+
Audio = 'Audio'
|
|
16
|
+
Graph = 'Graph'
|
|
17
|
+
HorizontalBar = 'HorizontalBar'
|
|
18
|
+
Text = 'Text'
|
|
19
|
+
ImageMask = 'ImageMask'
|
|
20
|
+
TextMask = 'TextMask'
|
|
21
|
+
RawData = 'RawData'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def default_image_visualizer(data: npt.NDArray[np.float32]) -> LeapImage:
|
|
25
|
+
rescaled_data = rescale_min_max(data[0])
|
|
26
|
+
return LeapImage(rescaled_data)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def default_video_visualizer(data: npt.NDArray[np.float32]) -> LeapVideo:
|
|
30
|
+
return LeapVideo(data[0])
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
_MAX_WAVEFORM_POINTS = 2000
|
|
34
|
+
_VISUAL_KINDS = ('waveform', 'spectrogram', 'image')
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _to_mono(audio: npt.NDArray) -> npt.NDArray:
|
|
38
|
+
a = np.squeeze(np.asarray(audio))
|
|
39
|
+
if a.ndim == 2: # mix down: channels are the shorter axis
|
|
40
|
+
a = a.mean(axis=int(np.argmin(a.shape)))
|
|
41
|
+
if a.ndim != 1:
|
|
42
|
+
raise ValueError(f'audio must be reducible to a mono 1-D signal, got shape {np.asarray(audio).shape}')
|
|
43
|
+
return a.astype(np.float32)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _waveform_graph(series: npt.NDArray, duration: float) -> LeapGraph:
|
|
47
|
+
s = np.squeeze(np.asarray(series)).astype(np.float32)
|
|
48
|
+
# ponytail: recharts chokes on 100k+ points; stride down for the default view. x_range keeps full time span.
|
|
49
|
+
step = max(1, s.shape[0] // _MAX_WAVEFORM_POINTS)
|
|
50
|
+
s = s[::step].reshape(-1, 1)
|
|
51
|
+
return LeapGraph(s, x_label='Time [s]', y_label='Amplitude', x_range=(0.0, duration))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def default_audio_visualizer(audio: npt.NDArray,
|
|
55
|
+
sample_rate: int,
|
|
56
|
+
visual: Optional[npt.NDArray] = None,
|
|
57
|
+
visual_kind: Optional[str] = None,
|
|
58
|
+
time_axis_index: int = -1) -> LeapAudio:
|
|
59
|
+
"""Package a playable audio sample plus the visual a playhead runs through.
|
|
60
|
+
|
|
61
|
+
audio: waveform samples (mono [N], or multi-channel that is mixed down).
|
|
62
|
+
sample_rate: samples per second.
|
|
63
|
+
visual: the array to display. For 'waveform' a 1-D series; for 'spectrogram'
|
|
64
|
+
a raw 2-D [freq, time] (or [time, freq]) array to be rendered grayscale;
|
|
65
|
+
for 'image' an already-rendered [H, W, 1] or [H, W, 3] image (e.g. a
|
|
66
|
+
spectrogram the caller already ran through their own colormap).
|
|
67
|
+
If omitted, a waveform graph is built from `audio` itself.
|
|
68
|
+
visual_kind: 'waveform', 'spectrogram', or 'image'. The caller states this
|
|
69
|
+
explicitly; the shape of `visual` is never inspected to guess it.
|
|
70
|
+
Required when `visual` is given; ignored when `visual` is omitted.
|
|
71
|
+
time_axis_index: for 'spectrogram', which axis of `visual` is time (moved to columns).
|
|
72
|
+
Unused for 'waveform'/'image'.
|
|
73
|
+
"""
|
|
74
|
+
mono = _to_mono(audio)
|
|
75
|
+
duration = mono.shape[0] / float(sample_rate)
|
|
76
|
+
x_range = (0.0, duration)
|
|
77
|
+
|
|
78
|
+
if visual is None: # no visual given: show the raw signal as a waveform
|
|
79
|
+
return LeapAudio(mono, sample_rate, _waveform_graph(mono, duration), x_range)
|
|
80
|
+
|
|
81
|
+
if visual_kind not in _VISUAL_KINDS:
|
|
82
|
+
raise ValueError(f"visual_kind must be one of {_VISUAL_KINDS}, got {visual_kind!r}")
|
|
83
|
+
|
|
84
|
+
v = np.asarray(visual)
|
|
85
|
+
|
|
86
|
+
if visual_kind == 'waveform':
|
|
87
|
+
return LeapAudio(mono, sample_rate, _waveform_graph(v, duration), x_range)
|
|
88
|
+
|
|
89
|
+
if visual_kind == 'image':
|
|
90
|
+
return LeapAudio(mono, sample_rate, LeapImage(v), x_range)
|
|
91
|
+
|
|
92
|
+
# spectrogram
|
|
93
|
+
spec = np.squeeze(v)
|
|
94
|
+
if spec.ndim != 2:
|
|
95
|
+
raise ValueError(f'spectrogram visual must be 2-D (freq x time), got shape {v.shape}')
|
|
96
|
+
if time_axis_index % spec.ndim == 0: # move time onto the horizontal axis (columns)
|
|
97
|
+
spec = spec.T
|
|
98
|
+
img = rescale_min_max(spec.astype(np.float32))[..., None] # [freq, time, 1]
|
|
99
|
+
return LeapAudio(mono, sample_rate, LeapImage(img), x_range)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def default_graph_visualizer(data: npt.NDArray[np.float32]) -> LeapGraph:
|
|
103
|
+
return LeapGraph(data[0])
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def default_horizontal_bar_visualizer(data: npt.NDArray[np.float32]) -> LeapHorizontalBar:
|
|
107
|
+
labels = [str(index) for index in range(data.shape[-1])]
|
|
108
|
+
return LeapHorizontalBar(data[0], labels)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def default_word_visualizer(data: npt.NDArray[np.float32]) -> LeapText:
|
|
112
|
+
if len(data.shape) == 2 and data.shape[0] == 1:
|
|
113
|
+
data = data[0]
|
|
114
|
+
if hasattr(data, 'tolist'):
|
|
115
|
+
data = data.tolist()
|
|
116
|
+
words = [str(index[0]) if type(index) is list else str(index) for index in data]
|
|
117
|
+
return LeapText(words)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def default_raw_data_visualizer(data: npt.NDArray[np.float32]) -> LeapText:
|
|
121
|
+
return LeapText([str(data)])
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def default_image_mask_visualizer(mask: npt.NDArray[np.float32], image: npt.NDArray[np.float32]) -> LeapImageMask:
|
|
125
|
+
if image.shape[0] == 1:
|
|
126
|
+
image = image[0]
|
|
127
|
+
if mask.shape[0] == 1:
|
|
128
|
+
mask = mask[0]
|
|
129
|
+
|
|
130
|
+
n_different_labels = mask.shape[-1]
|
|
131
|
+
labels = [str(i) for i in range(n_different_labels)]
|
|
132
|
+
|
|
133
|
+
if len(mask.shape) > 2:
|
|
134
|
+
if mask.shape[-1] == 1:
|
|
135
|
+
mask = np.squeeze(mask, axis=-1)
|
|
136
|
+
else:
|
|
137
|
+
mask = np.argmax(mask, axis=-1)
|
|
138
|
+
|
|
139
|
+
return LeapImageMask(mask.astype(np.uint8), image.astype(np.float32), labels)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def default_text_mask_visualizer(mask: npt.NDArray[np.float32], text_data: npt.NDArray[np.float32]) -> LeapTextMask:
|
|
143
|
+
mask = mask[0]
|
|
144
|
+
text_data = text_data[0]
|
|
145
|
+
|
|
146
|
+
words = default_word_visualizer(text_data).data
|
|
147
|
+
n_different_labels = mask.shape[-1]
|
|
148
|
+
labels = [str(i) for i in range(n_different_labels)]
|
|
149
|
+
|
|
150
|
+
if len(mask.shape) > 1:
|
|
151
|
+
if mask.shape[-1] == 1:
|
|
152
|
+
mask = np.squeeze(mask, axis=-1)
|
|
153
|
+
else:
|
|
154
|
+
mask = np.argmax(mask, axis=-1)
|
|
155
|
+
|
|
156
|
+
return LeapTextMask(mask.astype(np.uint8), words, labels)
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
import numpy.typing as npt
|
|
5
|
-
|
|
6
|
-
from code_loader.contract.visualizer_classes import LeapImage, LeapGraph, LeapHorizontalBar, LeapText, \
|
|
7
|
-
LeapImageMask, LeapTextMask, LeapVideo
|
|
8
|
-
from code_loader.utils import rescale_min_max
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class DefaultVisualizer(Enum):
|
|
12
|
-
Image = 'Image'
|
|
13
|
-
Video = 'Video'
|
|
14
|
-
Graph = 'Graph'
|
|
15
|
-
HorizontalBar = 'HorizontalBar'
|
|
16
|
-
Text = 'Text'
|
|
17
|
-
ImageMask = 'ImageMask'
|
|
18
|
-
TextMask = 'TextMask'
|
|
19
|
-
RawData = 'RawData'
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def default_image_visualizer(data: npt.NDArray[np.float32]) -> LeapImage:
|
|
23
|
-
rescaled_data = rescale_min_max(data[0])
|
|
24
|
-
return LeapImage(rescaled_data)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def default_video_visualizer(data: npt.NDArray[np.float32]) -> LeapVideo:
|
|
28
|
-
return LeapVideo(data[0])
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def default_graph_visualizer(data: npt.NDArray[np.float32]) -> LeapGraph:
|
|
32
|
-
return LeapGraph(data[0])
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def default_horizontal_bar_visualizer(data: npt.NDArray[np.float32]) -> LeapHorizontalBar:
|
|
36
|
-
labels = [str(index) for index in range(data.shape[-1])]
|
|
37
|
-
return LeapHorizontalBar(data[0], labels)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def default_word_visualizer(data: npt.NDArray[np.float32]) -> LeapText:
|
|
41
|
-
if len(data.shape) == 2 and data.shape[0] == 1:
|
|
42
|
-
data = data[0]
|
|
43
|
-
if hasattr(data, 'tolist'):
|
|
44
|
-
data = data.tolist()
|
|
45
|
-
words = [str(index[0]) if type(index) is list else str(index) for index in data]
|
|
46
|
-
return LeapText(words)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def default_raw_data_visualizer(data: npt.NDArray[np.float32]) -> LeapText:
|
|
50
|
-
return LeapText([str(data)])
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def default_image_mask_visualizer(mask: npt.NDArray[np.float32], image: npt.NDArray[np.float32]) -> LeapImageMask:
|
|
54
|
-
if image.shape[0] == 1:
|
|
55
|
-
image = image[0]
|
|
56
|
-
if mask.shape[0] == 1:
|
|
57
|
-
mask = mask[0]
|
|
58
|
-
|
|
59
|
-
n_different_labels = mask.shape[-1]
|
|
60
|
-
labels = [str(i) for i in range(n_different_labels)]
|
|
61
|
-
|
|
62
|
-
if len(mask.shape) > 2:
|
|
63
|
-
if mask.shape[-1] == 1:
|
|
64
|
-
mask = np.squeeze(mask, axis=-1)
|
|
65
|
-
else:
|
|
66
|
-
mask = np.argmax(mask, axis=-1)
|
|
67
|
-
|
|
68
|
-
return LeapImageMask(mask.astype(np.uint8), image.astype(np.float32), labels)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def default_text_mask_visualizer(mask: npt.NDArray[np.float32], text_data: npt.NDArray[np.float32]) -> LeapTextMask:
|
|
72
|
-
mask = mask[0]
|
|
73
|
-
text_data = text_data[0]
|
|
74
|
-
|
|
75
|
-
words = default_word_visualizer(text_data).data
|
|
76
|
-
n_different_labels = mask.shape[-1]
|
|
77
|
-
labels = [str(i) for i in range(n_different_labels)]
|
|
78
|
-
|
|
79
|
-
if len(mask.shape) > 1:
|
|
80
|
-
if mask.shape[-1] == 1:
|
|
81
|
-
mask = np.squeeze(mask, axis=-1)
|
|
82
|
-
else:
|
|
83
|
-
mask = np.argmax(mask, axis=-1)
|
|
84
|
-
|
|
85
|
-
return LeapTextMask(mask.astype(np.uint8), words, labels)
|
|
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
|
|
File without changes
|
{code_loader-1.0.198 → code_loader-1.0.200}/code_loader/experiment_api/experiment_context.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.198 → code_loader-1.0.200}/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
|