code-loader 1.0.199__tar.gz → 1.0.201__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.199 → code_loader-1.0.201}/PKG-INFO +1 -1
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/contract/datasetclasses.py +7 -5
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/contract/visualizer_classes.py +3 -10
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/inner_leap_binder/leapbinder.py +42 -6
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/inner_leap_binder/leapbinder_decorators.py +11 -4
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/leaploader.py +55 -28
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/leaploaderbase.py +8 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/visualizers/default_visualizers.py +21 -28
- {code_loader-1.0.199 → code_loader-1.0.201}/pyproject.toml +1 -1
- {code_loader-1.0.199 → code_loader-1.0.201}/LICENSE +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/README.md +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/__init__.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/contract/__init__.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/contract/enums.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/contract/exceptions.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/contract/mapping.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/contract/responsedataclasses.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/contract/sim_config.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/default_losses.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/default_metrics.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/__init__.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/api.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/cli_config_utils.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/client.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/epoch.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/experiment.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/experiment_context.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/types.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/utils.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/inner_leap_binder/__init__.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/mixpanel_tracker.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/plot_functions/__init__.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/plot_functions/plot_functions.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/plot_functions/visualize.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/utils.py +0 -0
- {code_loader-1.0.199 → code_loader-1.0.201}/code_loader/visualizers/__init__.py +0 -0
|
@@ -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,6 +309,7 @@ class MetadataHandler:
|
|
|
308
309
|
class CustomLatentSpaceHandler:
|
|
309
310
|
function: SectionCallableInterface
|
|
310
311
|
name: str = 'custom_latent_space'
|
|
312
|
+
use_ls_for_analysis: bool = False
|
|
311
313
|
|
|
312
314
|
|
|
313
315
|
# How a chain's latent-space vectors are derived from its per-step forward passes.
|
|
@@ -390,7 +392,7 @@ class DatasetIntegrationSetup:
|
|
|
390
392
|
metrics: List[MetricHandler] = field(default_factory=list)
|
|
391
393
|
instance_metrics: List[InstanceMetricHandler] = field(default_factory=list)
|
|
392
394
|
custom_layers: Dict[str, CustomLayerHandler] = field(default_factory=dict)
|
|
393
|
-
|
|
395
|
+
custom_latent_spaces: Dict[str, CustomLatentSpaceHandler] = field(default_factory=dict)
|
|
394
396
|
simulations: List[SimulationHandler] = field(default_factory=list)
|
|
395
397
|
autoregressive_step: Optional[AutoregressiveStepHandler] = None
|
|
396
398
|
autoregressive_metrics: List[AutoregressiveMetricHandler] = field(default_factory=list)
|
|
@@ -406,6 +408,6 @@ class DatasetSample:
|
|
|
406
408
|
metadata_is_none: Dict[str, bool]
|
|
407
409
|
index: Union[int, str]
|
|
408
410
|
state: DataStateEnum
|
|
409
|
-
|
|
411
|
+
custom_latent_spaces: Optional[Dict[str, npt.NDArray[np.float32]]] = None
|
|
410
412
|
instance_masks: Optional[Dict[str, ElementInstance]] = None
|
|
411
413
|
|
|
@@ -357,16 +357,14 @@ class LeapAudio:
|
|
|
357
357
|
should be mixed down before constructing LeapAudio.
|
|
358
358
|
sample_rate (int): Samples per second — needed to encode the clip and to map
|
|
359
359
|
the playhead position to time.
|
|
360
|
-
visual (Union[LeapImage, LeapGraph]): The thing you look at.
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
(0, N / sample_rate).
|
|
360
|
+
visual (Union[LeapImage, LeapGraph]): The thing you look at. For a waveform
|
|
361
|
+
the nested LeapGraph carries its own x_range (time span); the playhead is
|
|
362
|
+
driven by the audio element's currentTime, so no time range is needed here.
|
|
364
363
|
type (LeapDataType): The data type, default is LeapDataType.Audio.
|
|
365
364
|
"""
|
|
366
365
|
audio: npt.NDArray
|
|
367
366
|
sample_rate: int
|
|
368
367
|
visual: Union[LeapImage, LeapGraph]
|
|
369
|
-
x_range: Optional[Tuple[float, float]] = None
|
|
370
368
|
type: LeapDataType = LeapDataType.Audio
|
|
371
369
|
|
|
372
370
|
def __post_init__(self) -> None:
|
|
@@ -377,11 +375,6 @@ class LeapAudio:
|
|
|
377
375
|
'Audio visual must be a LeapImage (spectrogram) or LeapGraph (waveform)')
|
|
378
376
|
if not isinstance(self.sample_rate, int) or self.sample_rate <= 0:
|
|
379
377
|
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
378
|
|
|
386
379
|
|
|
387
380
|
map_leap_data_type_to_visualizer_class = {
|
|
@@ -536,18 +536,54 @@ 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
|
|
539
|
+
def set_custom_latent_space(self, function: SectionCallableInterface,
|
|
540
|
+
name: Optional[str] = None,
|
|
541
|
+
use_ls_for_analysis: bool = False) -> None:
|
|
540
542
|
"""
|
|
541
|
-
|
|
543
|
+
Register a custom latent space function.
|
|
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.
|
|
542
548
|
|
|
543
549
|
Args:
|
|
544
|
-
function (SectionCallableInterface): The
|
|
550
|
+
function (SectionCallableInterface): The latent-space handler function.
|
|
545
551
|
This function receives:
|
|
546
552
|
subset (PreprocessResponse): The subset of the data.
|
|
547
553
|
index (int): The index of the sample within the subset.
|
|
548
|
-
This function should numpy float32 array
|
|
554
|
+
This function should return a numpy float32 array containing the latent
|
|
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.
|
|
549
562
|
"""
|
|
550
|
-
|
|
563
|
+
if name is None:
|
|
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)
|
|
551
587
|
|
|
552
588
|
def set_autoregressive_step(self, function: AutoregressiveStepCallableInterface,
|
|
553
589
|
latent_space_aggregation: str = 'last_step') -> None:
|
|
@@ -958,7 +994,7 @@ class LeapBinder:
|
|
|
958
994
|
"Element instances are not supported together with tensorleap_autoregressive_step: "
|
|
959
995
|
"instance generation masks the sample's encoded inputs, which do not exist in an "
|
|
960
996
|
"autoregressive integration. Remove the instance encoders or the autoregressive hook.")
|
|
961
|
-
if self.setup_container.
|
|
997
|
+
if self.setup_container.custom_latent_spaces:
|
|
962
998
|
raise Exception(
|
|
963
999
|
"tensorleap_custom_latent_space is not supported together with "
|
|
964
1000
|
"tensorleap_autoregressive_step: the custom latent space function only sees "
|
{code_loader-1.0.199 → code_loader-1.0.201}/code_loader/inner_leap_binder/leapbinder_decorators.py
RENAMED
|
@@ -1703,8 +1703,14 @@ def tensorleap_metadata(
|
|
|
1703
1703
|
return decorating_function
|
|
1704
1704
|
|
|
1705
1705
|
|
|
1706
|
-
def tensorleap_custom_latent_space():
|
|
1706
|
+
def tensorleap_custom_latent_space(name: Optional[str] = None, use_ls_for_analysis: bool = False):
|
|
1707
|
+
assert isinstance(use_ls_for_analysis, bool), \
|
|
1708
|
+
("tensorleap_custom_latent_space validation failed: use_ls_for_analysis must be a bool. "
|
|
1709
|
+
f"Got {type(use_ls_for_analysis)}.")
|
|
1710
|
+
|
|
1707
1711
|
def decorating_function(user_function: SectionCallableInterface):
|
|
1712
|
+
ls_name = name if name is not None else user_function.__name__
|
|
1713
|
+
|
|
1708
1714
|
def _validate_input_args(sample_id: Union[int, str, list], preprocess_response: PreprocessResponse):
|
|
1709
1715
|
_validate_id_or_group(sample_id, preprocess_response, 'tensorleap_custom_latent_space')
|
|
1710
1716
|
|
|
@@ -1715,9 +1721,9 @@ def tensorleap_custom_latent_space():
|
|
|
1715
1721
|
if single_result.ndim > 1:
|
|
1716
1722
|
flat_dim = int(np.prod(single_result.shape))
|
|
1717
1723
|
store_general_warning(
|
|
1718
|
-
key=("tensorleap_custom_latent_space_flatten", tuple(single_result.shape)),
|
|
1724
|
+
key=("tensorleap_custom_latent_space_flatten", ls_name, tuple(single_result.shape)),
|
|
1719
1725
|
message=(
|
|
1720
|
-
f"tensorleap_custom_latent_space returned per-sample shape {tuple(single_result.shape)} "
|
|
1726
|
+
f"tensorleap_custom_latent_space '{ls_name}' returned per-sample shape {tuple(single_result.shape)} "
|
|
1721
1727
|
f"(ndim={single_result.ndim}). Tensorleap assumes per-sample shape (d, ...) and will "
|
|
1722
1728
|
f"flatten to ({flat_dim},) before downstream visualization and clustering. "
|
|
1723
1729
|
f"If you want a different aggregation (e.g. global average pooling), do it "
|
|
@@ -1760,7 +1766,8 @@ def tensorleap_custom_latent_space():
|
|
|
1760
1766
|
|
|
1761
1767
|
return result
|
|
1762
1768
|
|
|
1763
|
-
leap_binder.set_custom_latent_space(inner_without_validate
|
|
1769
|
+
leap_binder.set_custom_latent_space(inner_without_validate, ls_name,
|
|
1770
|
+
use_ls_for_analysis=use_ls_for_analysis)
|
|
1764
1771
|
|
|
1765
1772
|
def inner(sample_id, preprocess_response):
|
|
1766
1773
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
@@ -283,17 +283,7 @@ class LeapLoader(LeapLoaderBase):
|
|
|
283
283
|
|
|
284
284
|
metadata, metadata_is_none = self.get_metadata(state, sample_id)
|
|
285
285
|
|
|
286
|
-
|
|
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)
|
|
286
|
+
custom_latent_spaces = self._get_custom_latent_spaces(sample_id, preprocess_result[state])
|
|
297
287
|
instance_mask = self._get_instances_masks(state, sample_id, instance_id)
|
|
298
288
|
sample = DatasetSample(inputs=self._get_inputs(state, sample_id),
|
|
299
289
|
gt=None if state == DataStateEnum.unlabeled else self._get_gt(state, sample_id),
|
|
@@ -301,7 +291,7 @@ class LeapLoader(LeapLoaderBase):
|
|
|
301
291
|
metadata_is_none=metadata_is_none,
|
|
302
292
|
index=sample_id,
|
|
303
293
|
state=state,
|
|
304
|
-
|
|
294
|
+
custom_latent_spaces=custom_latent_spaces,
|
|
305
295
|
instance_masks=instance_mask)
|
|
306
296
|
return sample
|
|
307
297
|
|
|
@@ -332,11 +322,7 @@ class LeapLoader(LeapLoaderBase):
|
|
|
332
322
|
handler.name, handler_result
|
|
333
323
|
)
|
|
334
324
|
|
|
335
|
-
|
|
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
|
-
)
|
|
325
|
+
custom_latent_spaces = self._get_custom_latent_spaces(original_sample_id, preprocess)
|
|
340
326
|
|
|
341
327
|
return DatasetSample(
|
|
342
328
|
inputs=inputs,
|
|
@@ -345,7 +331,7 @@ class LeapLoader(LeapLoaderBase):
|
|
|
345
331
|
metadata_is_none=metadata_is_none,
|
|
346
332
|
index=synthetic_index,
|
|
347
333
|
state=DataStateEnum.additional,
|
|
348
|
-
|
|
334
|
+
custom_latent_spaces=custom_latent_spaces,
|
|
349
335
|
instance_masks=None,
|
|
350
336
|
)
|
|
351
337
|
|
|
@@ -1114,17 +1100,20 @@ class LeapLoader(LeapLoaderBase):
|
|
|
1114
1100
|
metadata[handler.name] = [v for v, _ in converted]
|
|
1115
1101
|
metadata_is_none[handler.name] = [is_none for _, is_none in converted]
|
|
1116
1102
|
|
|
1117
|
-
#
|
|
1118
|
-
# single call so a file-backed latent fn loads the file once, and normalize to
|
|
1119
|
-
# keeps the mandatory group path non-lossy. instance_masks stay None here: they are
|
|
1120
|
-
# per-(sample, instance) concern that needs an instance_id the group fetch does not carry.
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1103
|
+
# custom_latent_spaces are group-aware like the input/GT encoders: hand each the whole group
|
|
1104
|
+
# in a single call so a file-backed latent fn loads the file once, and normalize to per-sample
|
|
1105
|
+
# lists. This keeps the mandatory group path non-lossy. instance_masks stay None here: they are
|
|
1106
|
+
# a per-(sample, instance) concern that needs an instance_id the group fetch does not carry.
|
|
1107
|
+
latent_handlers = global_leap_binder.setup_container.custom_latent_spaces
|
|
1108
|
+
custom_latent_spaces = None
|
|
1109
|
+
if latent_handlers:
|
|
1110
|
+
custom_latent_spaces = {
|
|
1111
|
+
name: self._to_grouped_list(handler.function(group_ids, preprocess_state))
|
|
1112
|
+
for name, handler in latent_handlers.items()
|
|
1113
|
+
}
|
|
1125
1114
|
|
|
1126
1115
|
return DatasetSample(inputs=inputs, gt=gt, metadata=metadata, metadata_is_none=metadata_is_none,
|
|
1127
|
-
index=list(group_ids), state=state,
|
|
1116
|
+
index=list(group_ids), state=state, custom_latent_spaces=custom_latent_spaces,
|
|
1128
1117
|
instance_masks=None)
|
|
1129
1118
|
|
|
1130
1119
|
def _get_inputs(self, state: DataStateEnum, sample_id: Union[int, str]) -> Dict[str, npt.NDArray[np.float32]]:
|
|
@@ -1337,10 +1326,48 @@ class LeapLoader(LeapLoaderBase):
|
|
|
1337
1326
|
|
|
1338
1327
|
return id_type
|
|
1339
1328
|
|
|
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
|
+
|
|
1340
1344
|
@lru_cache()
|
|
1341
1345
|
def has_custom_latent_space_decorator(self) -> bool:
|
|
1342
1346
|
self.exec_script()
|
|
1343
|
-
return global_leap_binder.setup_container.
|
|
1347
|
+
return len(global_leap_binder.setup_container.custom_latent_spaces) > 0
|
|
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
|
|
1344
1371
|
|
|
1345
1372
|
@lru_cache()
|
|
1346
1373
|
def has_autoregressive_step(self) -> bool:
|
|
@@ -218,6 +218,14 @@ 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
|
+
|
|
221
229
|
@abstractmethod
|
|
222
230
|
def get_heatmap_visualizer_raw_vis_input_arg_name(self, visualizer_name: str) -> Optional[str]:
|
|
223
231
|
pass
|
|
@@ -31,7 +31,6 @@ def default_video_visualizer(data: npt.NDArray[np.float32]) -> LeapVideo:
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
_MAX_WAVEFORM_POINTS = 2000
|
|
34
|
-
_VISUAL_KINDS = ('waveform', 'spectrogram', 'image')
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
def _to_mono(audio: npt.NDArray) -> npt.NDArray:
|
|
@@ -54,49 +53,43 @@ def _waveform_graph(series: npt.NDArray, duration: float) -> LeapGraph:
|
|
|
54
53
|
def default_audio_visualizer(audio: npt.NDArray,
|
|
55
54
|
sample_rate: int,
|
|
56
55
|
visual: Optional[npt.NDArray] = None,
|
|
57
|
-
visual_kind: Optional[str] = None,
|
|
58
56
|
time_axis_index: int = -1) -> LeapAudio:
|
|
59
57
|
"""Package a playable audio sample plus the visual a playhead runs through.
|
|
60
58
|
|
|
61
59
|
audio: waveform samples (mono [N], or multi-channel that is mixed down).
|
|
62
60
|
sample_rate: samples per second.
|
|
63
|
-
visual: the array to display
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
visual: the array to display; its kind is deduced from its shape.
|
|
62
|
+
1-D [N] -> waveform graph of the samples.
|
|
63
|
+
2-D [H, W] -> spectrogram, rendered grayscale.
|
|
64
|
+
3-D [H, W, C] -> already-rendered image; C must be 3 (rgb) or 1 (grayscale).
|
|
67
65
|
If omitted, a waveform graph is built from `audio` itself.
|
|
68
|
-
|
|
69
|
-
|
|
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'.
|
|
66
|
+
time_axis_index: for a spectrogram, which axis of `visual` is time (moved to columns).
|
|
67
|
+
Unused otherwise.
|
|
73
68
|
"""
|
|
74
69
|
mono = _to_mono(audio)
|
|
75
70
|
duration = mono.shape[0] / float(sample_rate)
|
|
76
|
-
x_range = (0.0, duration)
|
|
77
71
|
|
|
78
72
|
if visual is None: # no visual given: show the raw signal as a waveform
|
|
79
|
-
return LeapAudio(mono, sample_rate, _waveform_graph(mono, duration)
|
|
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}")
|
|
73
|
+
return LeapAudio(mono, sample_rate, _waveform_graph(mono, duration))
|
|
83
74
|
|
|
84
75
|
v = np.asarray(visual)
|
|
85
76
|
|
|
86
|
-
if
|
|
87
|
-
return LeapAudio(mono, sample_rate, _waveform_graph(v, duration)
|
|
77
|
+
if v.ndim == 1: # waveform
|
|
78
|
+
return LeapAudio(mono, sample_rate, _waveform_graph(v, duration))
|
|
79
|
+
|
|
80
|
+
if v.ndim == 3: # already-rendered image
|
|
81
|
+
if v.shape[-1] not in (1, 3):
|
|
82
|
+
raise ValueError(f'image visual must have 1 (grayscale) or 3 (rgb) channels, got shape {v.shape}')
|
|
83
|
+
return LeapAudio(mono, sample_rate, LeapImage(v))
|
|
88
84
|
|
|
89
|
-
if
|
|
90
|
-
|
|
85
|
+
if v.ndim == 2: # spectrogram
|
|
86
|
+
spec = v
|
|
87
|
+
if time_axis_index % 2 == 0: # move time onto the horizontal axis (columns)
|
|
88
|
+
spec = spec.T
|
|
89
|
+
img = rescale_min_max(spec.astype(np.float32))[..., None] # [freq, time, 1]
|
|
90
|
+
return LeapAudio(mono, sample_rate, LeapImage(img))
|
|
91
91
|
|
|
92
|
-
|
|
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)
|
|
92
|
+
raise ValueError(f'visual must be 1-D, 2-D, or 3-D, got shape {v.shape}')
|
|
100
93
|
|
|
101
94
|
|
|
102
95
|
def default_graph_visualizer(data: npt.NDArray[np.float32]) -> LeapGraph:
|
|
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
|
|
File without changes
|
{code_loader-1.0.199 → code_loader-1.0.201}/code_loader/experiment_api/experiment_context.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_loader-1.0.199 → code_loader-1.0.201}/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
|