code-loader 1.0.138__py3-none-any.whl → 1.0.139.dev2__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.
Potentially problematic release.
This version of code-loader might be problematic. Click here for more details.
- code_loader/contract/datasetclasses.py +9 -1
- code_loader/inner_leap_binder/leapbinder_decorators.py +448 -95
- {code_loader-1.0.138.dist-info → code_loader-1.0.139.dev2.dist-info}/METADATA +1 -1
- {code_loader-1.0.138.dist-info → code_loader-1.0.139.dev2.dist-info}/RECORD +6 -6
- {code_loader-1.0.138.dist-info → code_loader-1.0.139.dev2.dist-info}/WHEEL +1 -1
- {code_loader-1.0.138.dist-info → code_loader-1.0.139.dev2.dist-info}/LICENSE +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import warnings
|
|
1
2
|
from dataclasses import dataclass, field
|
|
2
3
|
from typing import Any, Callable, List, Optional, Dict, Union, Type
|
|
3
4
|
import re
|
|
@@ -56,7 +57,14 @@ class PreprocessResponse:
|
|
|
56
57
|
for sample_id in self.sample_ids:
|
|
57
58
|
assert isinstance(sample_id, str), f"Sample id should be of type str. Got: {type(sample_id)}"
|
|
58
59
|
else:
|
|
59
|
-
raise Exception("length is deprecated.")
|
|
60
|
+
raise Exception("length is deprecated, please use sample_ids instead.")
|
|
61
|
+
|
|
62
|
+
if self.state is None:
|
|
63
|
+
warnings.warn(
|
|
64
|
+
"PreprocessResponse.state is not set. For best practice, assign a unique `state` value to each PreprocessResponse instance."
|
|
65
|
+
)
|
|
66
|
+
else:
|
|
67
|
+
assert isinstance(self.state, DataStateType), f"PreprocessResponse.state must be of type {DataStateType.__name__} but got {type(self.state)}"
|
|
60
68
|
|
|
61
69
|
def __hash__(self) -> int:
|
|
62
70
|
return id(self)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# mypy: ignore-errors
|
|
2
2
|
import os
|
|
3
|
+
import warnings
|
|
3
4
|
from collections import defaultdict
|
|
4
5
|
from functools import lru_cache
|
|
5
6
|
from pathlib import Path
|
|
6
|
-
from typing import Optional, Union, Callable, List, Dict
|
|
7
|
+
from typing import Optional, Union, Callable, List, Dict, get_args, get_origin
|
|
7
8
|
|
|
8
9
|
import numpy as np
|
|
9
10
|
import numpy.typing as npt
|
|
@@ -25,8 +26,116 @@ import functools
|
|
|
25
26
|
|
|
26
27
|
_called_from_inside_tl_decorator = 0
|
|
27
28
|
_called_from_inside_tl_integration_test_decorator = False
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
_update_env_status = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def validate_args_structure(*args, types_order, func_name, expected_names, **kwargs):
|
|
35
|
+
def _type_to_str(t):
|
|
36
|
+
origin = get_origin(t)
|
|
37
|
+
if origin is Union:
|
|
38
|
+
return " | ".join(tt.__name__ for tt in get_args(t))
|
|
39
|
+
elif hasattr(t, "__name__"):
|
|
40
|
+
return t.__name__
|
|
41
|
+
else:
|
|
42
|
+
return str(t)
|
|
43
|
+
|
|
44
|
+
def _format_types(types, names=None):
|
|
45
|
+
return ", ".join(
|
|
46
|
+
f"{(names[i] + ': ') if names else f'arg{i}: '}{_type_to_str(ty)}"
|
|
47
|
+
for i, ty in enumerate(types)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if expected_names:
|
|
51
|
+
normalized_args = []
|
|
52
|
+
for i, name in enumerate(expected_names):
|
|
53
|
+
if i < len(args):
|
|
54
|
+
normalized_args.append(args[i])
|
|
55
|
+
elif name in kwargs:
|
|
56
|
+
normalized_args.append(kwargs[name])
|
|
57
|
+
else:
|
|
58
|
+
raise AssertionError(
|
|
59
|
+
f"{func_name} validation failed: "
|
|
60
|
+
f"Missing required argument '{name}'. "
|
|
61
|
+
f"Expected arguments: {expected_names}."
|
|
62
|
+
)
|
|
63
|
+
else:
|
|
64
|
+
normalized_args = list(args)
|
|
65
|
+
if len(normalized_args) != len(types_order):
|
|
66
|
+
expected = _format_types(types_order, expected_names)
|
|
67
|
+
got_types = ", ".join(type(arg).__name__ for arg in normalized_args)
|
|
68
|
+
raise AssertionError(
|
|
69
|
+
f"{func_name} validation failed: "
|
|
70
|
+
f"Expected exactly {len(types_order)} arguments ({expected}), "
|
|
71
|
+
f"but got {len(normalized_args)} argument(s) of type(s): ({got_types}). "
|
|
72
|
+
f"Correct usage example: {func_name}({expected})"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
for i, (arg, expected_type) in enumerate(zip(normalized_args, types_order)):
|
|
76
|
+
origin = get_origin(expected_type)
|
|
77
|
+
if origin is Union:
|
|
78
|
+
allowed_types = get_args(expected_type)
|
|
79
|
+
else:
|
|
80
|
+
allowed_types = (expected_type,)
|
|
81
|
+
|
|
82
|
+
if not isinstance(arg, allowed_types):
|
|
83
|
+
allowed_str = " | ".join(t.__name__ for t in allowed_types)
|
|
84
|
+
raise AssertionError(
|
|
85
|
+
f"{func_name} validation failed: "
|
|
86
|
+
f"Argument '{expected_names[i] if expected_names else f'arg{i}'}' "
|
|
87
|
+
f"expected type {allowed_str}, but got {type(arg).__name__}. "
|
|
88
|
+
f"Correct usage example: {func_name}({_format_types(types_order, expected_names)})"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def validate_output_structure(result, func_name: str, expected_type_name="np.ndarray",gt_flag=False):
|
|
93
|
+
if result is None or (isinstance(result, float) and np.isnan(result)):
|
|
94
|
+
if gt_flag:
|
|
95
|
+
raise AssertionError(
|
|
96
|
+
f"{func_name} validation failed: "
|
|
97
|
+
f"The function returned {result!r}. "
|
|
98
|
+
f"If you are working with an unlabeled dataset and no ground truth is available, "
|
|
99
|
+
f"use 'return np.array([], dtype=np.float32)' instead. "
|
|
100
|
+
f"Otherwise, {func_name} expected a single {expected_type_name} object. "
|
|
101
|
+
f"Make sure the function ends with 'return <{expected_type_name}>'."
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
raise AssertionError(
|
|
105
|
+
f"{func_name} validation failed: "
|
|
106
|
+
f"The function returned None. "
|
|
107
|
+
f"Expected a single {expected_type_name} object. "
|
|
108
|
+
f"Make sure the function ends with 'return <{expected_type_name}>'."
|
|
109
|
+
)
|
|
110
|
+
if isinstance(result, tuple):
|
|
111
|
+
element_descriptions = [
|
|
112
|
+
f"[{i}] type: {type(r).__name__}"
|
|
113
|
+
for i, r in enumerate(result)
|
|
114
|
+
]
|
|
115
|
+
element_summary = "\n ".join(element_descriptions)
|
|
116
|
+
|
|
117
|
+
raise AssertionError(
|
|
118
|
+
f"{func_name} validation failed: "
|
|
119
|
+
f"The function returned multiple outputs ({len(result)} values), "
|
|
120
|
+
f"but only a single {expected_type_name} is allowed.\n\n"
|
|
121
|
+
f"Returned elements:\n"
|
|
122
|
+
f" {element_summary}\n\n"
|
|
123
|
+
f"Correct usage example:\n"
|
|
124
|
+
f" def {func_name}(...):\n"
|
|
125
|
+
f" return <{expected_type_name}>\n\n"
|
|
126
|
+
f"If you intended to return multiple values, combine them into a single "
|
|
127
|
+
f"{expected_type_name} (e.g., by concatenation or stacking)."
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def batch_warning(result, func_name):
|
|
131
|
+
if result.shape[0] == 1:
|
|
132
|
+
warnings.warn(
|
|
133
|
+
f"{func_name} warning: Tensorleap will add a batch dimension at axis 0 to the output of {func_name}, "
|
|
134
|
+
f"although the detected size of axis 0 is already 1. "
|
|
135
|
+
f"This may lead to an extra batch dimension (e.g., shape (1, 1, ...)). "
|
|
136
|
+
f"Please ensure that the output of '{func_name}' is not already batched "
|
|
137
|
+
f"to avoid computation errors."
|
|
138
|
+
)
|
|
30
139
|
def _add_mapping_connection(user_unique_name, connection_destinations, arg_names, name, node_mapping_type):
|
|
31
140
|
connection_destinations = [connection_destination for connection_destination in connection_destinations
|
|
32
141
|
if not isinstance(connection_destination, SamplePreprocessResponse)]
|
|
@@ -49,10 +158,23 @@ def tensorleap_integration_test():
|
|
|
49
158
|
def decorating_function(integration_test_function: Callable):
|
|
50
159
|
leap_binder.integration_test_func = integration_test_function
|
|
51
160
|
|
|
161
|
+
def _validate_input_args(*args, **kwargs):
|
|
162
|
+
sample_id,preprocess_response=args
|
|
163
|
+
assert type(sample_id) == preprocess_response.sample_id_type, (
|
|
164
|
+
f"tensorleap_integration_test validation failed: "
|
|
165
|
+
f"sample_id type ({type(sample_id).__name__}) does not match the expected "
|
|
166
|
+
f"type ({preprocess_response.sample_id_type}) from the PreprocessResponse."
|
|
167
|
+
)
|
|
168
|
+
|
|
52
169
|
def inner(*args, **kwargs):
|
|
170
|
+
validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
|
|
171
|
+
func_name='integration_test',expected_names=["idx", "preprocess"],**kwargs)
|
|
172
|
+
_validate_input_args(*args, **kwargs)
|
|
173
|
+
|
|
53
174
|
global _called_from_inside_tl_integration_test_decorator
|
|
54
175
|
try:
|
|
55
176
|
_called_from_inside_tl_integration_test_decorator = True
|
|
177
|
+
_update_env_status("tensorleap_integration_test", "v")#put here because otherwise it will become v only if it finishes all the script
|
|
56
178
|
ret = integration_test_function(*args, **kwargs)
|
|
57
179
|
|
|
58
180
|
try:
|
|
@@ -65,7 +187,7 @@ def tensorleap_integration_test():
|
|
|
65
187
|
line_number = first_tb.lineno
|
|
66
188
|
if isinstance(e, TypeError) and 'is not subscriptable' in str(e):
|
|
67
189
|
print(f'Invalid integration code. File {file_name}, line {line_number}: '
|
|
68
|
-
f'Please remove this indexing operation usage from the integration test code.
|
|
190
|
+
f"indexing is supported only on the model's predictions inside the integration test. Please remove this indexing operation usage from the integration test code.")
|
|
69
191
|
else:
|
|
70
192
|
print(f'Invalid integration code. File {file_name}, line {line_number}: '
|
|
71
193
|
f'Integration test is only allowed to call Tensorleap decorators. '
|
|
@@ -77,9 +199,9 @@ def tensorleap_integration_test():
|
|
|
77
199
|
_called_from_inside_tl_integration_test_decorator = False
|
|
78
200
|
|
|
79
201
|
leap_binder.check()
|
|
80
|
-
|
|
81
202
|
return inner
|
|
82
203
|
|
|
204
|
+
|
|
83
205
|
return decorating_function
|
|
84
206
|
|
|
85
207
|
def _safe_get_item(key):
|
|
@@ -89,18 +211,51 @@ def _safe_get_item(key):
|
|
|
89
211
|
raise Exception(f'Tensorleap currently supports models with no more then 10 inputs')
|
|
90
212
|
|
|
91
213
|
def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]] = []):
|
|
214
|
+
assert isinstance(prediction_types, list),(
|
|
215
|
+
f"tensorleap_load_model validation failed: "
|
|
216
|
+
f" prediction_types is an optional argument of type List[PredictionTypeHandler]] but got {type(prediction_types).__name__}."
|
|
217
|
+
)
|
|
92
218
|
for i, prediction_type in enumerate(prediction_types):
|
|
219
|
+
assert isinstance(prediction_type, PredictionTypeHandler),(f"tensorleap_load_model validation failed: "
|
|
220
|
+
f" prediction_types at position {i} must be of type PredictionTypeHandler but got {type(prediction_types[i]).__name__}.")
|
|
93
221
|
leap_binder.add_prediction(prediction_type.name, prediction_type.labels, prediction_type.channel_dim, i)
|
|
94
222
|
|
|
223
|
+
def _validate_result(result) -> None:
|
|
224
|
+
valid_types=["onnxruntime","keras"]
|
|
225
|
+
err_message=f"tensorleap_load_model validation failed:\nSupported models are Keras and onnxruntime only and non of them was returned."
|
|
226
|
+
validate_output_structure(result, func_name="tensorleap_load_model", expected_type_name= [" | ".join(t for t in valid_types)][0])
|
|
227
|
+
try:
|
|
228
|
+
import keras
|
|
229
|
+
except ImportError:
|
|
230
|
+
keras = None
|
|
231
|
+
try:
|
|
232
|
+
import onnxruntime
|
|
233
|
+
except ImportError:
|
|
234
|
+
onnxruntime = None
|
|
235
|
+
|
|
236
|
+
if not keras and not onnxruntime:
|
|
237
|
+
raise AssertionError(err_message)
|
|
238
|
+
|
|
239
|
+
is_keras_model = bool(keras and isinstance(result, getattr(keras, "Model", tuple())))
|
|
240
|
+
is_onnx_model = bool(onnxruntime and isinstance(result, onnxruntime.InferenceSession))
|
|
241
|
+
|
|
242
|
+
if not any([is_keras_model, is_onnx_model]):
|
|
243
|
+
raise AssertionError( err_message)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
|
|
95
247
|
def decorating_function(load_model_func):
|
|
96
248
|
class TempMapping:
|
|
97
249
|
pass
|
|
98
250
|
|
|
99
251
|
@lru_cache()
|
|
100
|
-
def inner():
|
|
252
|
+
def inner(*args, **kwargs):
|
|
253
|
+
validate_args_structure(*args, types_order=[],
|
|
254
|
+
func_name='tensorleap_load_model',expected_names=[],**kwargs)
|
|
101
255
|
class ModelPlaceholder:
|
|
102
256
|
def __init__(self):
|
|
103
|
-
self.model = load_model_func()
|
|
257
|
+
self.model = load_model_func() #TODO- check why this fails on onnx model
|
|
258
|
+
_validate_result(self.model)
|
|
104
259
|
|
|
105
260
|
# keras interface
|
|
106
261
|
def __call__(self, arg):
|
|
@@ -164,8 +319,9 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
|
|
|
164
319
|
|
|
165
320
|
def get_inputs(self):
|
|
166
321
|
return self.model.get_inputs()
|
|
167
|
-
|
|
168
|
-
|
|
322
|
+
model_placeholder=ModelPlaceholder()
|
|
323
|
+
_update_env_status("tensorleap_load_model", "v")
|
|
324
|
+
return model_placeholder
|
|
169
325
|
|
|
170
326
|
def mapping_inner():
|
|
171
327
|
class ModelOutputPlaceholder:
|
|
@@ -228,12 +384,11 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
|
|
|
228
384
|
|
|
229
385
|
return ModelPlaceholder()
|
|
230
386
|
|
|
231
|
-
def final_inner():
|
|
387
|
+
def final_inner(*args, **kwargs):
|
|
232
388
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
233
389
|
return mapping_inner()
|
|
234
390
|
else:
|
|
235
|
-
return inner()
|
|
236
|
-
|
|
391
|
+
return inner(*args, **kwargs)
|
|
237
392
|
return final_inner
|
|
238
393
|
|
|
239
394
|
return decorating_function
|
|
@@ -244,81 +399,168 @@ def tensorleap_custom_metric(name: str,
|
|
|
244
399
|
compute_insights: Optional[Union[bool, Dict[str, bool]]] = None,
|
|
245
400
|
connects_to=None):
|
|
246
401
|
name_to_unique_name = defaultdict(set)
|
|
247
|
-
|
|
248
402
|
def decorating_function(
|
|
249
403
|
user_function: Union[CustomCallableInterfaceMultiArgs, CustomMultipleReturnCallableInterfaceMultiArgs,
|
|
250
404
|
ConfusionMatrixCallableInterfaceMultiArgs]):
|
|
405
|
+
|
|
406
|
+
def _validate_decorators_signature():
|
|
407
|
+
err_message = f"{user_function.__name__} validation failed.\n"
|
|
408
|
+
if not isinstance(name, str):
|
|
409
|
+
raise TypeError(err_message + f"`name` must be a string, got type {type(name).__name__}.")
|
|
410
|
+
valid_directions = {MetricDirection.Upward, MetricDirection.Downward}
|
|
411
|
+
if isinstance(direction, MetricDirection):
|
|
412
|
+
if direction not in valid_directions:
|
|
413
|
+
raise ValueError(
|
|
414
|
+
err_message +
|
|
415
|
+
f"Invalid MetricDirection: {direction}. Must be one of {valid_directions}, "
|
|
416
|
+
f"got type {type(direction).__name__}."
|
|
417
|
+
)
|
|
418
|
+
elif isinstance(direction, dict):
|
|
419
|
+
if not all(isinstance(k, str) for k in direction.keys()):
|
|
420
|
+
invalid_keys = {k: type(k).__name__ for k in direction.keys() if not isinstance(k, str)}
|
|
421
|
+
raise TypeError(
|
|
422
|
+
err_message +
|
|
423
|
+
f"All keys in `direction` must be strings, got invalid key types: {invalid_keys}."
|
|
424
|
+
)
|
|
425
|
+
for k, v in direction.items():
|
|
426
|
+
if v not in valid_directions:
|
|
427
|
+
raise ValueError(
|
|
428
|
+
err_message +
|
|
429
|
+
f"Invalid direction for key '{k}': {v}. Must be one of {valid_directions}, "
|
|
430
|
+
f"got type {type(v).__name__}."
|
|
431
|
+
)
|
|
432
|
+
else:
|
|
433
|
+
raise TypeError(
|
|
434
|
+
err_message +
|
|
435
|
+
f"`direction` must be a MetricDirection or a Dict[str, MetricDirection], "
|
|
436
|
+
f"got type {type(direction).__name__}."
|
|
437
|
+
)
|
|
438
|
+
if compute_insights is not None:
|
|
439
|
+
if not isinstance(compute_insights, (bool, dict)):
|
|
440
|
+
raise TypeError(
|
|
441
|
+
err_message +
|
|
442
|
+
f"`compute_insights` must be a bool or a Dict[str, bool], "
|
|
443
|
+
f"got type {type(compute_insights).__name__}."
|
|
444
|
+
)
|
|
445
|
+
if isinstance(compute_insights, dict):
|
|
446
|
+
if not all(isinstance(k, str) for k in compute_insights.keys()):
|
|
447
|
+
invalid_keys = {k: type(k).__name__ for k in compute_insights.keys() if not isinstance(k, str)}
|
|
448
|
+
raise TypeError(
|
|
449
|
+
err_message +
|
|
450
|
+
f"All keys in `compute_insights` must be strings, got invalid key types: {invalid_keys}."
|
|
451
|
+
)
|
|
452
|
+
for k, v in compute_insights.items():
|
|
453
|
+
if not isinstance(v, bool):
|
|
454
|
+
raise TypeError(
|
|
455
|
+
err_message +
|
|
456
|
+
f"Invalid type for compute_insights['{k}']: expected bool, got type {type(v).__name__}."
|
|
457
|
+
)
|
|
458
|
+
if connects_to is not None:
|
|
459
|
+
valid_types = (str, list, tuple, set)
|
|
460
|
+
if not isinstance(connects_to, valid_types):
|
|
461
|
+
raise TypeError(
|
|
462
|
+
err_message +
|
|
463
|
+
f"`connects_to` must be one of {valid_types}, got type {type(connects_to).__name__}."
|
|
464
|
+
)
|
|
465
|
+
if isinstance(connects_to, (list, tuple, set)):
|
|
466
|
+
invalid_elems = [f"{type(e).__name__}" for e in connects_to if not isinstance(e, str)]
|
|
467
|
+
if invalid_elems:
|
|
468
|
+
raise TypeError(
|
|
469
|
+
err_message +
|
|
470
|
+
f"All elements in `connects_to` must be strings, "
|
|
471
|
+
f"but found element types: {invalid_elems}."
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
_validate_decorators_signature()
|
|
476
|
+
|
|
251
477
|
for metric_handler in leap_binder.setup_container.metrics:
|
|
252
478
|
if metric_handler.metric_handler_data.name == name:
|
|
253
479
|
raise Exception(f'Metric with name {name} already exists. '
|
|
254
480
|
f'Please choose another')
|
|
255
481
|
|
|
256
482
|
def _validate_input_args(*args, **kwargs) -> None:
|
|
483
|
+
assert len(args) > 0, (
|
|
484
|
+
f"{user_function.__name__}() validation failed: "
|
|
485
|
+
f"Expected at least one positional|key-word argument of type np.ndarray, "
|
|
486
|
+
f"but received none. "
|
|
487
|
+
f"Correct usage example: tensorleap_custom_metric(input_array: np.ndarray, ...)"
|
|
488
|
+
)
|
|
257
489
|
for i, arg in enumerate(args):
|
|
258
490
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
259
|
-
f'
|
|
491
|
+
f'{user_function.__name__}() validation failed: '
|
|
260
492
|
f'Argument #{i} should be a numpy array. Got {type(arg)}.')
|
|
261
493
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
262
494
|
assert arg.shape[0] == leap_binder.batch_size_to_validate, \
|
|
263
|
-
(f'
|
|
495
|
+
(f'{user_function.__name__}() validation failed: Argument #{i} '
|
|
264
496
|
f'first dim should be as the batch size. Got {arg.shape[0]} '
|
|
265
497
|
f'instead of {leap_binder.batch_size_to_validate}')
|
|
266
498
|
|
|
267
499
|
for _arg_name, arg in kwargs.items():
|
|
268
500
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
269
|
-
f'
|
|
501
|
+
f'{user_function.__name__}() validation failed: '
|
|
270
502
|
f'Argument {_arg_name} should be a numpy array. Got {type(arg)}.')
|
|
271
503
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
272
504
|
assert arg.shape[0] == leap_binder.batch_size_to_validate, \
|
|
273
|
-
(f'
|
|
505
|
+
(f'{user_function.__name__}() validation failed: Argument {_arg_name} '
|
|
274
506
|
f'first dim should be as the batch size. Got {arg.shape[0]} '
|
|
275
507
|
f'instead of {leap_binder.batch_size_to_validate}')
|
|
276
508
|
|
|
277
509
|
def _validate_result(result) -> None:
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
510
|
+
validate_output_structure(result, func_name=user_function.__name__,
|
|
511
|
+
expected_type_name="List[float | int | None | List[ConfusionMatrixElement] ] | NDArray[np.float32] or dictonary with one of these types as its values types")
|
|
512
|
+
supported_types_message = (f'{user_function.__name__}() validation failed: '
|
|
513
|
+
f'{user_function.__name__}() has returned unsupported type.\nSupported types are List[float|int|None], '
|
|
514
|
+
f'List[List[ConfusionMatrixElement]], NDArray[np.float32] or dictonary with one of these types as its values types. ')
|
|
281
515
|
|
|
282
|
-
def _validate_single_metric(single_metric_result):
|
|
516
|
+
def _validate_single_metric(single_metric_result,key=None):
|
|
283
517
|
if isinstance(single_metric_result, list):
|
|
284
518
|
if isinstance(single_metric_result[0], list):
|
|
285
|
-
assert isinstance(single_metric_result[0]
|
|
286
|
-
f
|
|
519
|
+
assert all(isinstance(cm, ConfusionMatrixElement) for cm in single_metric_result[0]), (
|
|
520
|
+
f"{supported_types_message} "
|
|
521
|
+
f"Got {'a dict where the value of ' + str(key) + ' is of type ' if key is not None else ''}"
|
|
522
|
+
f"List[List[{', '.join(type(cm).__name__ for cm in single_metric_result[0])}]]."
|
|
523
|
+
)
|
|
524
|
+
|
|
287
525
|
else:
|
|
288
|
-
assert isinstance(single_metric_result
|
|
289
|
-
|
|
290
|
-
|
|
526
|
+
assert all(isinstance(v, (float,int,type(None),np.float32)) for v in single_metric_result), (
|
|
527
|
+
f"{supported_types_message}\n"
|
|
528
|
+
f"Got {'a dict where the value of ' + str(key) + ' is of type ' if key is not None else ''}"
|
|
529
|
+
f"List[{', '.join(type(v).__name__ for v in single_metric_result)}]."
|
|
530
|
+
)
|
|
291
531
|
else:
|
|
292
532
|
assert isinstance(single_metric_result,
|
|
293
|
-
np.ndarray), f'{supported_types_message}
|
|
294
|
-
assert len(single_metric_result.shape) == 1, (f'
|
|
533
|
+
np.ndarray), f'{supported_types_message}\nGot {type(single_metric_result)}.'
|
|
534
|
+
assert len(single_metric_result.shape) == 1, (f'{user_function.__name__}() validation failed: '
|
|
295
535
|
f'The return shape should be 1D. Got {len(single_metric_result.shape)}D.')
|
|
296
536
|
|
|
297
537
|
if leap_binder.batch_size_to_validate:
|
|
298
538
|
assert len(single_metric_result) == leap_binder.batch_size_to_validate, \
|
|
299
|
-
f'
|
|
539
|
+
f'{user_function.__name__}() validation failed: The return len {f"of srt{key} value" if key is not None else ""} should be as the batch size.'
|
|
300
540
|
|
|
301
541
|
if isinstance(result, dict):
|
|
302
542
|
for key, value in result.items():
|
|
543
|
+
_validate_single_metric(value,key)
|
|
544
|
+
|
|
303
545
|
assert isinstance(key, str), \
|
|
304
|
-
(f'
|
|
546
|
+
(f'{user_function.__name__}() validation failed: '
|
|
305
547
|
f'Keys in the return dict should be of type str. Got {type(key)}.')
|
|
306
548
|
_validate_single_metric(value)
|
|
307
549
|
|
|
308
550
|
if isinstance(direction, dict):
|
|
309
551
|
for direction_key in direction:
|
|
310
552
|
assert direction_key in result, \
|
|
311
|
-
(f'
|
|
553
|
+
(f'{user_function.__name__}() validation failed: '
|
|
312
554
|
f'Keys in the direction mapping should be part of result keys. Got key {direction_key}.')
|
|
313
555
|
|
|
314
556
|
if compute_insights is not None:
|
|
315
557
|
assert isinstance(compute_insights, dict), \
|
|
316
|
-
(f'
|
|
558
|
+
(f'{user_function.__name__}() validation failed: '
|
|
317
559
|
f'compute_insights should be dict if using the dict results. Got {type(compute_insights)}.')
|
|
318
560
|
|
|
319
561
|
for ci_key in compute_insights:
|
|
320
562
|
assert ci_key in result, \
|
|
321
|
-
(f'
|
|
563
|
+
(f'{user_function.__name__}() validation failed: '
|
|
322
564
|
f'Keys in the compute_insights mapping should be part of result keys. Got key {ci_key}.')
|
|
323
565
|
|
|
324
566
|
else:
|
|
@@ -326,7 +568,7 @@ def tensorleap_custom_metric(name: str,
|
|
|
326
568
|
|
|
327
569
|
if compute_insights is not None:
|
|
328
570
|
assert isinstance(compute_insights, bool), \
|
|
329
|
-
(f'
|
|
571
|
+
(f'{user_function.__name__}() validation failed: '
|
|
330
572
|
f'compute_insights should be boolean. Got {type(compute_insights)}.')
|
|
331
573
|
|
|
332
574
|
@functools.wraps(user_function)
|
|
@@ -358,6 +600,7 @@ def tensorleap_custom_metric(name: str,
|
|
|
358
600
|
result = inner_without_validate(*args, **kwargs)
|
|
359
601
|
|
|
360
602
|
_validate_result(result)
|
|
603
|
+
_update_env_status("tensorleap_custom_metric","v")
|
|
361
604
|
return result
|
|
362
605
|
|
|
363
606
|
def mapping_inner(*args, **kwargs):
|
|
@@ -397,28 +640,38 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
397
640
|
name_to_unique_name = defaultdict(set)
|
|
398
641
|
|
|
399
642
|
def decorating_function(user_function: VisualizerCallableInterface):
|
|
643
|
+
assert isinstance(visualizer_type,LeapDataType),(f"{user_function.__name__} validation failed: "
|
|
644
|
+
f"visualizer_type should be of type {LeapDataType.__name__} but got {type(visualizer_type)}"
|
|
645
|
+
)
|
|
646
|
+
|
|
400
647
|
for viz_handler in leap_binder.setup_container.visualizers:
|
|
401
648
|
if viz_handler.visualizer_handler_data.name == name:
|
|
402
649
|
raise Exception(f'Visualizer with name {name} already exists. '
|
|
403
650
|
f'Please choose another')
|
|
404
651
|
|
|
405
652
|
def _validate_input_args(*args, **kwargs):
|
|
653
|
+
assert len(args) > 0, (
|
|
654
|
+
f"{user_function.__name__}() validation failed: "
|
|
655
|
+
f"Expected at least one positional|key-word argument of type np.ndarray, "
|
|
656
|
+
f"but received none. "
|
|
657
|
+
f"Correct usage example: {user_function.__name__}(input_array: np.ndarray, ...)"
|
|
658
|
+
)
|
|
406
659
|
for i, arg in enumerate(args):
|
|
407
660
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
408
|
-
f'
|
|
661
|
+
f'{user_function.__name__}() validation failed: '
|
|
409
662
|
f'Argument #{i} should be a numpy array. Got {type(arg)}.')
|
|
410
663
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
411
664
|
assert arg.shape[0] != leap_binder.batch_size_to_validate, \
|
|
412
|
-
(f'
|
|
665
|
+
(f'{user_function.__name__}() validation failed: '
|
|
413
666
|
f'Argument #{i} should be without batch dimension. ')
|
|
414
667
|
|
|
415
668
|
for _arg_name, arg in kwargs.items():
|
|
416
669
|
assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
|
|
417
|
-
f'
|
|
670
|
+
f'{user_function.__name__}() validation failed: '
|
|
418
671
|
f'Argument {_arg_name} should be a numpy array. Got {type(arg)}.')
|
|
419
672
|
if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
|
|
420
673
|
assert arg.shape[0] != leap_binder.batch_size_to_validate, \
|
|
421
|
-
(f'
|
|
674
|
+
(f'{user_function.__name__}() validation failed: Argument {_arg_name} '
|
|
422
675
|
f'should be without batch dimension. ')
|
|
423
676
|
|
|
424
677
|
def _validate_result(result):
|
|
@@ -432,8 +685,11 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
432
685
|
LeapDataType.ImageWithBBox: LeapImageWithBBox,
|
|
433
686
|
LeapDataType.ImageWithHeatmap: LeapImageWithHeatmap
|
|
434
687
|
}
|
|
688
|
+
validate_output_structure(result, func_name=user_function.__name__,
|
|
689
|
+
expected_type_name=result_type_map[visualizer_type])
|
|
690
|
+
|
|
435
691
|
assert isinstance(result, result_type_map[visualizer_type]), \
|
|
436
|
-
(f'
|
|
692
|
+
(f'{user_function.__name__}() validation failed: '
|
|
437
693
|
f'The return type should be {result_type_map[visualizer_type]}. Got {type(result)}.')
|
|
438
694
|
|
|
439
695
|
@functools.wraps(user_function)
|
|
@@ -465,6 +721,7 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
|
|
|
465
721
|
result = inner_without_validate(*args, **kwargs)
|
|
466
722
|
|
|
467
723
|
_validate_result(result)
|
|
724
|
+
_update_env_status("tensorleap_custom_visualizer","v")
|
|
468
725
|
return result
|
|
469
726
|
|
|
470
727
|
def mapping_inner(*args, **kwargs):
|
|
@@ -506,30 +763,26 @@ def tensorleap_metadata(
|
|
|
506
763
|
f'Please choose another')
|
|
507
764
|
|
|
508
765
|
def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
|
|
509
|
-
assert isinstance(sample_id, (int, str)), \
|
|
510
|
-
(f'tensorleap_metadata validation failed: '
|
|
511
|
-
f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
|
|
512
|
-
assert isinstance(preprocess_response, PreprocessResponse), \
|
|
513
|
-
(f'tensorleap_metadata validation failed: '
|
|
514
|
-
f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
|
|
515
766
|
assert type(sample_id) == preprocess_response.sample_id_type, \
|
|
516
|
-
(f'
|
|
767
|
+
(f'{user_function.__name__}() validation failed: '
|
|
517
768
|
f'Argument sample_id should be as the same type as defined in the preprocess response '
|
|
518
769
|
f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
|
|
519
770
|
|
|
520
771
|
def _validate_result(result):
|
|
521
772
|
supported_result_types = (type(None), int, str, bool, float, dict, np.floating,
|
|
522
773
|
np.bool_, np.unsignedinteger, np.signedinteger, np.integer)
|
|
774
|
+
validate_output_structure(result, func_name=user_function.__name__,
|
|
775
|
+
expected_type_name=supported_result_types)
|
|
523
776
|
assert isinstance(result, supported_result_types), \
|
|
524
|
-
(f'
|
|
777
|
+
(f'{user_function.__name__}() validation failed: '
|
|
525
778
|
f'Unsupported return type. Got {type(result)}. should be any of {str(supported_result_types)}')
|
|
526
779
|
if isinstance(result, dict):
|
|
527
780
|
for key, value in result.items():
|
|
528
781
|
assert isinstance(key, str), \
|
|
529
|
-
(f'
|
|
782
|
+
(f'{user_function.__name__}() validation failed: '
|
|
530
783
|
f'Keys in the return dict should be of type str. Got {type(key)}.')
|
|
531
784
|
assert isinstance(value, supported_result_types), \
|
|
532
|
-
(f'
|
|
785
|
+
(f'{user_function.__name__}() validation failed: '
|
|
533
786
|
f'Values in the return dict should be of type {str(supported_result_types)}. Got {type(value)}.')
|
|
534
787
|
|
|
535
788
|
def inner_without_validate(sample_id, preprocess_response):
|
|
@@ -546,15 +799,18 @@ def tensorleap_metadata(
|
|
|
546
799
|
|
|
547
800
|
leap_binder.set_metadata(inner_without_validate, name, metadata_type)
|
|
548
801
|
|
|
549
|
-
def inner(
|
|
802
|
+
def inner(*args,**kwargs):
|
|
550
803
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
551
804
|
return None
|
|
552
|
-
|
|
805
|
+
validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
|
|
806
|
+
func_name=user_function.__name__, expected_names=["idx", "preprocess"],**kwargs)
|
|
807
|
+
sample_id, preprocess_response = args if len(args)!=0 else kwargs.values()
|
|
553
808
|
_validate_input_args(sample_id, preprocess_response)
|
|
554
809
|
|
|
555
810
|
result = inner_without_validate(sample_id, preprocess_response)
|
|
556
811
|
|
|
557
812
|
_validate_result(result)
|
|
813
|
+
_update_env_status("tensorleap_metadata","v")
|
|
558
814
|
return result
|
|
559
815
|
|
|
560
816
|
return inner
|
|
@@ -617,19 +873,23 @@ def tensorleap_preprocess():
|
|
|
617
873
|
|
|
618
874
|
def _validate_input_args(*args, **kwargs):
|
|
619
875
|
assert len(args) == 0 and len(kwargs) == 0, \
|
|
620
|
-
(f'
|
|
876
|
+
(f'{user_function.__name__}() validation failed: '
|
|
621
877
|
f'The function should not take any arguments. Got {args} and {kwargs}.')
|
|
622
878
|
|
|
623
879
|
def _validate_result(result):
|
|
624
|
-
assert isinstance(result, list),
|
|
625
|
-
(
|
|
626
|
-
|
|
880
|
+
assert isinstance(result, list), (
|
|
881
|
+
f"{user_function.__name__}() validation failed: expected return type list[{PreprocessResponse.__name__}]"
|
|
882
|
+
f"(e.g., [PreprocessResponse1, PreprocessResponse2, ...]), but returned type is {type(result).__name__}."
|
|
883
|
+
if not isinstance(result, tuple)
|
|
884
|
+
else f"{user_function.__name__}() validation failed: expected to return a single list[{PreprocessResponse.__name__}] object, "
|
|
885
|
+
f"but returned {len(result)} objects instead."
|
|
886
|
+
)
|
|
627
887
|
for i, response in enumerate(result):
|
|
628
888
|
assert isinstance(response, PreprocessResponse), \
|
|
629
|
-
(f'
|
|
889
|
+
(f'{user_function.__name__}() validation failed: '
|
|
630
890
|
f'Element #{i} in the return list should be a PreprocessResponse. Got {type(response)}.')
|
|
631
891
|
assert len(set(result)) == len(result), \
|
|
632
|
-
(f'
|
|
892
|
+
(f'{user_function.__name__}() validation failed: '
|
|
633
893
|
f'The return list should not contain duplicate PreprocessResponse objects.')
|
|
634
894
|
|
|
635
895
|
def inner(*args, **kwargs):
|
|
@@ -637,9 +897,9 @@ def tensorleap_preprocess():
|
|
|
637
897
|
return [None, None, None, None]
|
|
638
898
|
|
|
639
899
|
_validate_input_args(*args, **kwargs)
|
|
640
|
-
|
|
641
900
|
result = user_function()
|
|
642
901
|
_validate_result(result)
|
|
902
|
+
_update_env_status("tensorleap_preprocess", "v")
|
|
643
903
|
return result
|
|
644
904
|
|
|
645
905
|
return inner
|
|
@@ -838,29 +1098,23 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
838
1098
|
raise Exception(f"Channel dim for input {name} is expected to be either -1 or positive")
|
|
839
1099
|
|
|
840
1100
|
def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
|
|
841
|
-
assert isinstance(sample_id, (int, str)), \
|
|
842
|
-
(f'tensorleap_input_encoder validation failed: '
|
|
843
|
-
f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
|
|
844
|
-
assert isinstance(preprocess_response, PreprocessResponse), \
|
|
845
|
-
(f'tensorleap_input_encoder validation failed: '
|
|
846
|
-
f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
|
|
847
1101
|
assert type(sample_id) == preprocess_response.sample_id_type, \
|
|
848
|
-
(f'
|
|
1102
|
+
(f'{user_function.__name__}() validation failed: '
|
|
849
1103
|
f'Argument sample_id should be as the same type as defined in the preprocess response '
|
|
850
1104
|
f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
|
|
851
1105
|
|
|
852
1106
|
def _validate_result(result):
|
|
1107
|
+
validate_output_structure(result, func_name=user_function.__name__, expected_type_name = "np.ndarray")
|
|
853
1108
|
assert isinstance(result, np.ndarray), \
|
|
854
|
-
(f'
|
|
1109
|
+
(f'{user_function.__name__}() validation failed: '
|
|
855
1110
|
f'Unsupported return type. Should be a numpy array. Got {type(result)}.')
|
|
856
1111
|
assert result.dtype == np.float32, \
|
|
857
|
-
(f'
|
|
1112
|
+
(f'{user_function.__name__}() validation failed: '
|
|
858
1113
|
f'The return type should be a numpy array of type float32. Got {result.dtype}.')
|
|
859
|
-
assert channel_dim - 1 <= len(result.shape), (f'
|
|
1114
|
+
assert channel_dim - 1 <= len(result.shape), (f'{user_function.__name__}() validation failed: '
|
|
860
1115
|
f'The channel_dim ({channel_dim}) should be <= to the rank of the resulting input rank ({len(result.shape)}).')
|
|
861
1116
|
|
|
862
1117
|
def inner_without_validate(sample_id, preprocess_response):
|
|
863
|
-
|
|
864
1118
|
global _called_from_inside_tl_decorator
|
|
865
1119
|
_called_from_inside_tl_decorator += 1
|
|
866
1120
|
|
|
@@ -874,7 +1128,10 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
874
1128
|
leap_binder.set_input(inner_without_validate, name, channel_dim=channel_dim)
|
|
875
1129
|
|
|
876
1130
|
|
|
877
|
-
def inner(
|
|
1131
|
+
def inner(*args, **kwargs):
|
|
1132
|
+
validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
|
|
1133
|
+
func_name=user_function.__name__, expected_names=["idx", "preprocess"], **kwargs)
|
|
1134
|
+
sample_id, preprocess_response = args if len(args)!=0 else kwargs.values()
|
|
878
1135
|
_validate_input_args(sample_id, preprocess_response)
|
|
879
1136
|
|
|
880
1137
|
result = inner_without_validate(sample_id, preprocess_response)
|
|
@@ -882,18 +1139,19 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
882
1139
|
_validate_result(result)
|
|
883
1140
|
|
|
884
1141
|
if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
|
|
1142
|
+
batch_warning(result,user_function.__name__)
|
|
885
1143
|
result = np.expand_dims(result, axis=0)
|
|
1144
|
+
_update_env_status("tensorleap_input_encoder", "v")
|
|
886
1145
|
|
|
887
1146
|
return result
|
|
888
1147
|
|
|
889
1148
|
|
|
890
|
-
|
|
891
1149
|
node_mapping_type = NodeMappingType.Input
|
|
892
1150
|
if model_input_index is not None:
|
|
893
1151
|
node_mapping_type = NodeMappingType(f'Input{str(model_input_index)}')
|
|
894
1152
|
inner.node_mapping = NodeMapping(name, node_mapping_type)
|
|
895
1153
|
|
|
896
|
-
def mapping_inner(
|
|
1154
|
+
def mapping_inner(*args, **kwargs):
|
|
897
1155
|
class TempMapping:
|
|
898
1156
|
pass
|
|
899
1157
|
|
|
@@ -905,11 +1163,11 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
|
|
|
905
1163
|
|
|
906
1164
|
mapping_inner.node_mapping = NodeMapping(name, node_mapping_type)
|
|
907
1165
|
|
|
908
|
-
def final_inner(
|
|
1166
|
+
def final_inner(*args, **kwargs):
|
|
909
1167
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
910
|
-
return mapping_inner(
|
|
1168
|
+
return mapping_inner(*args, **kwargs)
|
|
911
1169
|
else:
|
|
912
|
-
return inner(
|
|
1170
|
+
return inner(*args, **kwargs)
|
|
913
1171
|
|
|
914
1172
|
final_inner.node_mapping = NodeMapping(name, node_mapping_type)
|
|
915
1173
|
|
|
@@ -926,23 +1184,18 @@ def tensorleap_gt_encoder(name: str):
|
|
|
926
1184
|
f'Please choose another')
|
|
927
1185
|
|
|
928
1186
|
def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
|
|
929
|
-
assert isinstance(sample_id, (int, str)), \
|
|
930
|
-
(f'tensorleap_gt_encoder validation failed: '
|
|
931
|
-
f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
|
|
932
|
-
assert isinstance(preprocess_response, PreprocessResponse), \
|
|
933
|
-
(f'tensorleap_gt_encoder validation failed: '
|
|
934
|
-
f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
|
|
935
1187
|
assert type(sample_id) == preprocess_response.sample_id_type, \
|
|
936
|
-
(f'
|
|
1188
|
+
(f'{user_function.__name__}() validation failed: '
|
|
937
1189
|
f'Argument sample_id should be as the same type as defined in the preprocess response '
|
|
938
1190
|
f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
|
|
939
1191
|
|
|
940
1192
|
def _validate_result(result):
|
|
1193
|
+
validate_output_structure(result, func_name=user_function.__name__, expected_type_name = "np.ndarray",gt_flag=True)
|
|
941
1194
|
assert isinstance(result, np.ndarray), \
|
|
942
|
-
(f'
|
|
1195
|
+
(f'{user_function.__name__}() validation failed: '
|
|
943
1196
|
f'Unsupported return type. Should be a numpy array. Got {type(result)}.')
|
|
944
1197
|
assert result.dtype == np.float32, \
|
|
945
|
-
(f'
|
|
1198
|
+
(f'{user_function.__name__}() validation failed: '
|
|
946
1199
|
f'The return type should be a numpy array of type float32. Got {result.dtype}.')
|
|
947
1200
|
|
|
948
1201
|
def inner_without_validate(sample_id, preprocess_response):
|
|
@@ -959,7 +1212,10 @@ def tensorleap_gt_encoder(name: str):
|
|
|
959
1212
|
leap_binder.set_ground_truth(inner_without_validate, name)
|
|
960
1213
|
|
|
961
1214
|
|
|
962
|
-
def inner(
|
|
1215
|
+
def inner(*args, **kwargs):
|
|
1216
|
+
validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
|
|
1217
|
+
func_name=user_function.__name__, expected_names=["idx", "preprocess"], **kwargs)
|
|
1218
|
+
sample_id, preprocess_response = args
|
|
963
1219
|
_validate_input_args(sample_id, preprocess_response)
|
|
964
1220
|
|
|
965
1221
|
result = inner_without_validate(sample_id, preprocess_response)
|
|
@@ -967,13 +1223,15 @@ def tensorleap_gt_encoder(name: str):
|
|
|
967
1223
|
_validate_result(result)
|
|
968
1224
|
|
|
969
1225
|
if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
|
|
1226
|
+
batch_warning(result, user_function.__name__)
|
|
970
1227
|
result = np.expand_dims(result, axis=0)
|
|
1228
|
+
_update_env_status("tensorleap_gt_encoder", "v")
|
|
971
1229
|
|
|
972
1230
|
return result
|
|
973
1231
|
|
|
974
1232
|
inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
|
|
975
1233
|
|
|
976
|
-
def mapping_inner(
|
|
1234
|
+
def mapping_inner(*args, **kwargs):
|
|
977
1235
|
class TempMapping:
|
|
978
1236
|
pass
|
|
979
1237
|
|
|
@@ -984,11 +1242,11 @@ def tensorleap_gt_encoder(name: str):
|
|
|
984
1242
|
|
|
985
1243
|
mapping_inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
|
|
986
1244
|
|
|
987
|
-
def final_inner(
|
|
1245
|
+
def final_inner(*args, **kwargs):
|
|
988
1246
|
if os.environ.get(mapping_runtime_mode_env_var_mame):
|
|
989
|
-
return mapping_inner(
|
|
1247
|
+
return mapping_inner(*args, **kwargs)
|
|
990
1248
|
else:
|
|
991
|
-
return inner(
|
|
1249
|
+
return inner(*args, **kwargs)
|
|
992
1250
|
|
|
993
1251
|
final_inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
|
|
994
1252
|
|
|
@@ -1009,28 +1267,37 @@ def tensorleap_custom_loss(name: str, connects_to=None):
|
|
|
1009
1267
|
valid_types = (np.ndarray, SamplePreprocessResponse)
|
|
1010
1268
|
|
|
1011
1269
|
def _validate_input_args(*args, **kwargs):
|
|
1270
|
+
assert len(args) > 0 and len(kwargs)==0, (
|
|
1271
|
+
f"{user_function.__name__}() validation failed: "
|
|
1272
|
+
f"Expected at least one positional|key-word argument of the allowed types (np.ndarray|SamplePreprocessResponse|list(np.ndarray|SamplePreprocessResponse)). "
|
|
1273
|
+
f"but received none. "
|
|
1274
|
+
f"Correct usage example: {user_function.__name__}(input_array: np.ndarray, ...)"
|
|
1275
|
+
)
|
|
1012
1276
|
for i, arg in enumerate(args):
|
|
1013
1277
|
if isinstance(arg, list):
|
|
1014
1278
|
for y, elem in enumerate(arg):
|
|
1015
|
-
assert isinstance(elem, valid_types), (f'
|
|
1279
|
+
assert isinstance(elem, valid_types), (f'{user_function.__name__}() validation failed: '
|
|
1016
1280
|
f'Element #{y} of list should be a numpy array. Got {type(elem)}.')
|
|
1017
1281
|
else:
|
|
1018
|
-
assert isinstance(arg, valid_types), (f'
|
|
1282
|
+
assert isinstance(arg, valid_types), (f'{user_function.__name__}() validation failed: '
|
|
1019
1283
|
f'Argument #{i} should be a numpy array. Got {type(arg)}.')
|
|
1020
1284
|
for _arg_name, arg in kwargs.items():
|
|
1021
1285
|
if isinstance(arg, list):
|
|
1022
1286
|
for y, elem in enumerate(arg):
|
|
1023
|
-
assert isinstance(elem, valid_types), (f'
|
|
1287
|
+
assert isinstance(elem, valid_types), (f'{user_function.__name__}() validation failed: '
|
|
1024
1288
|
f'Element #{y} of list should be a numpy array. Got {type(elem)}.')
|
|
1025
1289
|
else:
|
|
1026
|
-
assert isinstance(arg, valid_types), (f'
|
|
1290
|
+
assert isinstance(arg, valid_types), (f'{user_function.__name__}() validation failed: '
|
|
1027
1291
|
f'Argument #{_arg_name} should be a numpy array. Got {type(arg)}.')
|
|
1028
1292
|
|
|
1029
1293
|
def _validate_result(result):
|
|
1294
|
+
validate_output_structure(result, func_name=user_function.__name__,
|
|
1295
|
+
expected_type_name="np.ndarray")
|
|
1030
1296
|
assert isinstance(result, np.ndarray), \
|
|
1031
|
-
(f'
|
|
1297
|
+
(f'{user_function.__name__} validation failed: '
|
|
1032
1298
|
f'The return type should be a numpy array. Got {type(result)}.')
|
|
1033
|
-
|
|
1299
|
+
assert result.ndim<2 ,(f'{user_function.__name__} validation failed: '
|
|
1300
|
+
f'The return type should be a 1Dim numpy array but got {result.ndim}Dim.')
|
|
1034
1301
|
|
|
1035
1302
|
@functools.wraps(user_function)
|
|
1036
1303
|
def inner_without_validate(*args, **kwargs):
|
|
@@ -1061,6 +1328,8 @@ def tensorleap_custom_loss(name: str, connects_to=None):
|
|
|
1061
1328
|
result = inner_without_validate(*args, **kwargs)
|
|
1062
1329
|
|
|
1063
1330
|
_validate_result(result)
|
|
1331
|
+
_update_env_status("tensorleap_custom_loss", "v")
|
|
1332
|
+
|
|
1064
1333
|
return result
|
|
1065
1334
|
|
|
1066
1335
|
def mapping_inner(*args, **kwargs):
|
|
@@ -1117,3 +1386,87 @@ def tensorleap_custom_layer(name: str):
|
|
|
1117
1386
|
return custom_layer
|
|
1118
1387
|
|
|
1119
1388
|
return decorating_function
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
def tensorleap_status_table():
|
|
1392
|
+
'''
|
|
1393
|
+
Usage example:
|
|
1394
|
+
###################
|
|
1395
|
+
leap_integration.py
|
|
1396
|
+
###################
|
|
1397
|
+
from code_loader.inner_leap_binder.leapbinder_decorators import tensorleap_status_table
|
|
1398
|
+
...
|
|
1399
|
+
...
|
|
1400
|
+
...
|
|
1401
|
+
if __name__ == '__main__':
|
|
1402
|
+
tensorleap_status_table()
|
|
1403
|
+
...
|
|
1404
|
+
'''
|
|
1405
|
+
import atexit
|
|
1406
|
+
import sys
|
|
1407
|
+
import traceback
|
|
1408
|
+
|
|
1409
|
+
|
|
1410
|
+
table = [
|
|
1411
|
+
{"name": "tensorleap_preprocess", "status": "x"},
|
|
1412
|
+
{"name": "tensorleap_integration_test", "status": "x"},
|
|
1413
|
+
{"name": "tensorleap_input_encoder", "status": "x"},
|
|
1414
|
+
{"name": "tensorleap_gt_encoder", "status": "x"},
|
|
1415
|
+
{"name": "tensorleap_load_model", "status": "x"},
|
|
1416
|
+
{"name": "tensorleap_custom_loss", "status": "x"},
|
|
1417
|
+
{"name": "tensorleap_custom_metric (optional)", "status": "x"},
|
|
1418
|
+
{"name": "tensorleap_metadata (optional)", "status": "x"},
|
|
1419
|
+
{"name": "tensorleap_custom_visualizer (optional)", "status": "x"},
|
|
1420
|
+
|
|
1421
|
+
]
|
|
1422
|
+
|
|
1423
|
+
_finalizer_called = {"done": False}
|
|
1424
|
+
|
|
1425
|
+
def _print_table():
|
|
1426
|
+
ready_mess = "\nAll parts have been successfully set. If no errors accured, you can now push the project to the Tensorleap system."
|
|
1427
|
+
not_ready_mess = "\nSome mandatory components have not been set yet. Recommended next implementation step: "
|
|
1428
|
+
mandatory_ready_mess = "\nAll mandatory parts have been successfully set. If no errors accured, you can now push the project to the Tensorleap system or continue to the next optional implementation step: "
|
|
1429
|
+
|
|
1430
|
+
name_width = max(len(row["name"]) for row in table)
|
|
1431
|
+
status_width = max(len(row["status"]) for row in table)
|
|
1432
|
+
header = f"{'Function Name'.ljust(name_width)} | {'Status'.ljust(status_width)}"
|
|
1433
|
+
sep = "-" * len(header)
|
|
1434
|
+
print("\n" + header)
|
|
1435
|
+
print(sep)
|
|
1436
|
+
ready=True
|
|
1437
|
+
for row in table:
|
|
1438
|
+
print(f"{row['name'].ljust(name_width)} | {row['status'].ljust(status_width)}")
|
|
1439
|
+
if row['status']=='x' and ready:
|
|
1440
|
+
ready=False
|
|
1441
|
+
next_step=row['name']
|
|
1442
|
+
|
|
1443
|
+
|
|
1444
|
+
print(ready_mess) if ready else print(mandatory_ready_mess+next_step) if "optional" in next_step else print(not_ready_mess+next_step)
|
|
1445
|
+
def update_env_params(name: str, status: str = "✓"):
|
|
1446
|
+
for row in table:
|
|
1447
|
+
if row["name"].removesuffix(" (optional)") == name:
|
|
1448
|
+
row["status"] = status
|
|
1449
|
+
break
|
|
1450
|
+
def run_on_exit():
|
|
1451
|
+
if _finalizer_called["done"]:
|
|
1452
|
+
return
|
|
1453
|
+
_finalizer_called["done"] = True
|
|
1454
|
+
_print_table()
|
|
1455
|
+
def handle_exception(exc_type, exc_value, exc_traceback):
|
|
1456
|
+
traceback.print_exception(exc_type, exc_value, exc_traceback)
|
|
1457
|
+
run_on_exit()
|
|
1458
|
+
atexit.register(run_on_exit)
|
|
1459
|
+
sys.excepthook = handle_exception
|
|
1460
|
+
global _update_env_status
|
|
1461
|
+
_update_env_status = update_env_params
|
|
1462
|
+
return update_env_params
|
|
1463
|
+
|
|
1464
|
+
|
|
1465
|
+
|
|
1466
|
+
|
|
1467
|
+
|
|
1468
|
+
|
|
1469
|
+
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
|
|
2
2
|
code_loader/__init__.py,sha256=outxRQ0M-zMfV0QGVJmAed5qWfRmyD0TV6-goEGAzBw,406
|
|
3
3
|
code_loader/contract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
code_loader/contract/datasetclasses.py,sha256=
|
|
4
|
+
code_loader/contract/datasetclasses.py,sha256=hkHMU1upWzVWkjIBoU3r14XPDleicif4Oia2xfuHgvQ,9395
|
|
5
5
|
code_loader/contract/enums.py,sha256=GEFkvUMXnCNt-GOoz7NJ9ecQZ2PPDettJNOsxsiM0wk,1622
|
|
6
6
|
code_loader/contract/exceptions.py,sha256=jWqu5i7t-0IG0jGRsKF4DjJdrsdpJjIYpUkN1F4RiyQ,51
|
|
7
7
|
code_loader/contract/mapping.py,sha256=sWJhpng-IkOzQnWQdMT5w2ZZ3X1Z_OOzSwCLXIS7oxE,1446
|
|
@@ -21,7 +21,7 @@ code_loader/experiment_api/utils.py,sha256=XZHtxge12TS4H4-8PjV3sKuhp8Ud6ojAiIzTZ
|
|
|
21
21
|
code_loader/experiment_api/workingspace_config_utils.py,sha256=DLzXQCg4dgTV_YgaSbeTVzq-2ja_SQw4zi7LXwKL9cY,990
|
|
22
22
|
code_loader/inner_leap_binder/__init__.py,sha256=koOlJyMNYzGbEsoIbXathSmQ-L38N_pEXH_HvL7beXU,99
|
|
23
23
|
code_loader/inner_leap_binder/leapbinder.py,sha256=Q3D9yVM-GNEJfYRFvMV__BoZbcWOgnWKhrZXAv6Tu7o,33232
|
|
24
|
-
code_loader/inner_leap_binder/leapbinder_decorators.py,sha256=
|
|
24
|
+
code_loader/inner_leap_binder/leapbinder_decorators.py,sha256=NlH8W1q8kVAik81EJ9ZNjWkAm8XPSW-XrKh9wBgd5BA,69593
|
|
25
25
|
code_loader/leaploader.py,sha256=6D6xZzMI6qSNIb3tuKLB3BbK5H8QS1_r7iQjIXO3OkM,29795
|
|
26
26
|
code_loader/leaploaderbase.py,sha256=LIFcC6xo6V_iiGN3BjibXETu_l84EWM_WIOKAvkfTiM,4458
|
|
27
27
|
code_loader/mixpanel_tracker.py,sha256=l9z_szKKQ7apEbdNZpGH1TKAiT_TsBHb9AQnePaWTyo,4942
|
|
@@ -31,7 +31,7 @@ code_loader/plot_functions/visualize.py,sha256=gsBAYYkwMh7jIpJeDMPS8G4CW-pxwx6Lz
|
|
|
31
31
|
code_loader/utils.py,sha256=gXENTYpjdidq2dx0gVbXlErPeHoNs-4TYAZbLRe0y2c,2712
|
|
32
32
|
code_loader/visualizers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
33
|
code_loader/visualizers/default_visualizers.py,sha256=onRnLE_TXfgLN4o52hQIOOhUcFexGlqJ3xSpQDVLuZM,2604
|
|
34
|
-
code_loader-1.0.
|
|
35
|
-
code_loader-1.0.
|
|
36
|
-
code_loader-1.0.
|
|
37
|
-
code_loader-1.0.
|
|
34
|
+
code_loader-1.0.139.dev2.dist-info/LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
|
|
35
|
+
code_loader-1.0.139.dev2.dist-info/METADATA,sha256=bZ4R5F5wQdWZEg666Lxiw1LxHcqUCmRXsgKvxFUGof4,1095
|
|
36
|
+
code_loader-1.0.139.dev2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
37
|
+
code_loader-1.0.139.dev2.dist-info/RECORD,,
|
|
File without changes
|