code-loader 1.0.184.dev4__py3-none-any.whl → 1.0.184.dev5__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.
@@ -1091,6 +1091,170 @@ def tensorleap_custom_instances_metric(name: str,
1091
1091
  return decorating_function
1092
1092
 
1093
1093
 
1094
+ # ---- visualizer semantic warnings (local-only) ----
1095
+ # These fire only when NOT running on the platform. They catch inputs that are
1096
+ # structurally valid (pass the Leap*.__post_init__ type/shape checks) but render
1097
+ # badly given how the platform draws them (see code_loader/plot_functions).
1098
+ _VIZ_DOCS = "https://docs.tensorleap.ai/tensorleap-integration/writing-integration-code/visualizers"
1099
+
1100
+
1101
+ def _viz_prefix(viz_name: str, leap_type_name: str) -> str:
1102
+ return f"Visualizer '{viz_name}' ({leap_type_name}):"
1103
+
1104
+
1105
+ def _warn_image_value_range(image, viz_name: str, leap_type_name: str, field_name: str = "image data") -> None:
1106
+ """Warn when image pixel values sit in a range that will render near-black or clipped."""
1107
+ if not isinstance(image, np.ndarray) or image.size == 0:
1108
+ return
1109
+ prefix = _viz_prefix(viz_name, leap_type_name)
1110
+
1111
+ if np.issubdtype(image.dtype, np.floating):
1112
+ if not np.all(np.isfinite(image)):
1113
+ store_general_warning(
1114
+ key=("viz_image_nonfinite", viz_name, leap_type_name, field_name),
1115
+ message=f"{prefix} {field_name} contains NaN or Inf values, which will render incorrectly.",
1116
+ link_to_docs=_VIZ_DOCS,
1117
+ )
1118
+ finite = image[np.isfinite(image)]
1119
+ if finite.size == 0:
1120
+ return
1121
+ mn, mx = float(finite.min()), float(finite.max())
1122
+ if 0.0 <= mn and mx <= 1.0 and mx > 0.0:
1123
+ store_general_warning(
1124
+ key=("viz_image_unit_range", viz_name, leap_type_name, field_name),
1125
+ message=(f"{prefix} {field_name} is float with values in [{mn:.3g}, {mx:.3g}] - looks normalized "
1126
+ f"to [0,1]. Tensorleap renders images by casting to int, so this will appear near-black. "
1127
+ f"Scale to [0,255] or cast to uint8 before visualizing."),
1128
+ link_to_docs=_VIZ_DOCS,
1129
+ )
1130
+ elif mn < 0.0 or mx > 255.0:
1131
+ store_general_warning(
1132
+ key=("viz_image_out_of_range", viz_name, leap_type_name, field_name),
1133
+ message=(f"{prefix} {field_name} is float with values in [{mn:.3g}, {mx:.3g}], outside the "
1134
+ f"displayable [0,255] range - looks like a normalized model input (e.g. standardized or "
1135
+ f"scaled to [-1,1]). Values will be clipped and the image will render incorrectly. "
1136
+ f"De-normalize back to [0,255] before visualizing."),
1137
+ link_to_docs=_VIZ_DOCS,
1138
+ )
1139
+ elif np.issubdtype(image.dtype, np.integer):
1140
+ mn, mx = int(image.min()), int(image.max())
1141
+ if mx <= 1:
1142
+ store_general_warning(
1143
+ key=("viz_image_int_low", viz_name, leap_type_name, field_name),
1144
+ message=(f"{prefix} {field_name} is uint8 but values span only [{mn}, {mx}] - this will appear "
1145
+ f"near-black. If the data is normalized to [0,1], scale to [0,255] before casting to uint8."),
1146
+ link_to_docs=_VIZ_DOCS,
1147
+ )
1148
+
1149
+
1150
+ def _warn_bbox_coords(bounding_boxes, viz_name: str, leap_type_name: str) -> None:
1151
+ """Warn when bbox coords are not relative [0,1] (i.e. look like absolute pixels)."""
1152
+ for bbox in bounding_boxes:
1153
+ vals = [bbox.x, bbox.y, bbox.width, bbox.height]
1154
+ if any(v is not None and (v > 1.0 or v < 0.0) for v in vals):
1155
+ store_general_warning(
1156
+ key=("viz_bbox_relative", viz_name, leap_type_name),
1157
+ message=(f"{_viz_prefix(viz_name, leap_type_name)} bounding box coordinates (x, y, width, height) "
1158
+ f"should be relative to image size, in [0,1]. Got values outside [0,1] - looks like absolute "
1159
+ f"pixel coordinates. Boxes will be drawn off-image. Divide coordinates by image width/height."),
1160
+ link_to_docs=_VIZ_DOCS,
1161
+ )
1162
+ return
1163
+
1164
+
1165
+ def _warn_hbar(leap_data, viz_name: str, leap_type_name: str) -> None:
1166
+ body, labels, gt = leap_data.body, leap_data.labels, leap_data.gt
1167
+ if len(body) != len(labels):
1168
+ store_general_warning(
1169
+ key=("viz_hbar_body_labels", viz_name, leap_type_name),
1170
+ message=(f"{_viz_prefix(viz_name, leap_type_name)} body length ({len(body)}) does not match labels "
1171
+ f"length ({len(labels)}). Bars and labels will be misaligned or truncated."),
1172
+ link_to_docs=_VIZ_DOCS,
1173
+ )
1174
+ if gt is not None and len(gt) != len(body):
1175
+ store_general_warning(
1176
+ key=("viz_hbar_gt_body", viz_name, leap_type_name),
1177
+ message=(f"{_viz_prefix(viz_name, leap_type_name)} gt length ({len(gt)}) does not match body length "
1178
+ f"({len(body)}). Prediction and GT bars will be misaligned."),
1179
+ link_to_docs=_VIZ_DOCS,
1180
+ )
1181
+
1182
+
1183
+ def _warn_image_mask(leap_data, viz_name: str, leap_type_name: str) -> None:
1184
+ mask, image, labels = leap_data.mask, leap_data.image, leap_data.labels
1185
+ if tuple(mask.shape) != tuple(image.shape[:2]):
1186
+ store_general_warning(
1187
+ key=("viz_mask_shape", viz_name, leap_type_name),
1188
+ message=(f"{_viz_prefix(viz_name, leap_type_name)} mask shape {tuple(mask.shape)} does not match image "
1189
+ f"H x W {tuple(image.shape[:2])}. The mask overlay will fail or be misaligned."),
1190
+ link_to_docs=_VIZ_DOCS,
1191
+ )
1192
+ nonzero = np.unique(mask)
1193
+ nonzero = nonzero[nonzero != 0]
1194
+ if len(nonzero) != len(labels):
1195
+ store_general_warning(
1196
+ key=("viz_mask_labels", viz_name, leap_type_name),
1197
+ message=(f"{_viz_prefix(viz_name, leap_type_name)} mask has {len(nonzero)} distinct non-zero value(s) "
1198
+ f"but {len(labels)} label(s) were provided. Some regions may be uncolored or some labels unused."),
1199
+ link_to_docs=_VIZ_DOCS,
1200
+ )
1201
+
1202
+
1203
+ def _warn_text_mask(leap_data, viz_name: str, leap_type_name: str) -> None:
1204
+ mask, text, labels = leap_data.mask, leap_data.text, leap_data.labels
1205
+ if len(mask) != len(text):
1206
+ store_general_warning(
1207
+ key=("viz_textmask_len", viz_name, leap_type_name),
1208
+ message=(f"{_viz_prefix(viz_name, leap_type_name)} mask length ({len(mask)}) does not match text length "
1209
+ f"({len(text)}). Tokens will be dropped or misaligned (zip truncates to the shorter one)."),
1210
+ link_to_docs=_VIZ_DOCS,
1211
+ )
1212
+ if mask.size > 0 and int(mask.max()) > len(labels):
1213
+ store_general_warning(
1214
+ key=("viz_textmask_labels", viz_name, leap_type_name),
1215
+ message=(f"{_viz_prefix(viz_name, leap_type_name)} mask has values up to {int(mask.max())} but only "
1216
+ f"{len(labels)} label(s) were provided. Colors will wrap and label mapping will be wrong."),
1217
+ link_to_docs=_VIZ_DOCS,
1218
+ )
1219
+
1220
+
1221
+ def _warn_image_with_heatmap(leap_data, viz_name: str, leap_type_name: str) -> None:
1222
+ image, heatmaps = leap_data.image, leap_data.heatmaps
1223
+ if heatmaps.ndim >= 3 and tuple(heatmaps.shape[1:3]) != tuple(image.shape[:2]):
1224
+ store_general_warning(
1225
+ key=("viz_heatmap_shape", viz_name, leap_type_name),
1226
+ message=(f"{_viz_prefix(viz_name, leap_type_name)} heatmap spatial size {tuple(heatmaps.shape[1:3])} "
1227
+ f"does not match image H x W {tuple(image.shape[:2])}. The heatmap overlay will be stretched "
1228
+ f"or misaligned."),
1229
+ link_to_docs=_VIZ_DOCS,
1230
+ )
1231
+ _warn_image_value_range(image, viz_name, leap_type_name)
1232
+
1233
+
1234
+ def _emit_visualizer_warnings(result, viz_name: str, visualizer_type: LeapDataType) -> None:
1235
+ """Dispatch semantic warning checks per visualizer type. Never raises."""
1236
+ try:
1237
+ leap_type_name = visualizer_type.name
1238
+ if visualizer_type == LeapDataType.Image:
1239
+ _warn_image_value_range(result.data, viz_name, leap_type_name)
1240
+ elif visualizer_type == LeapDataType.ImageWithBBox:
1241
+ _warn_image_value_range(result.data, viz_name, leap_type_name)
1242
+ _warn_bbox_coords(result.bounding_boxes, viz_name, leap_type_name)
1243
+ elif visualizer_type == LeapDataType.Video:
1244
+ _warn_image_value_range(result.data, viz_name, leap_type_name, field_name="video data")
1245
+ elif visualizer_type == LeapDataType.ImageMask:
1246
+ _warn_image_value_range(result.image, viz_name, leap_type_name)
1247
+ _warn_image_mask(result, viz_name, leap_type_name)
1248
+ elif visualizer_type == LeapDataType.ImageWithHeatmap:
1249
+ _warn_image_with_heatmap(result, viz_name, leap_type_name)
1250
+ elif visualizer_type == LeapDataType.HorizontalBar:
1251
+ _warn_hbar(result, viz_name, leap_type_name)
1252
+ elif visualizer_type == LeapDataType.TextMask:
1253
+ _warn_text_mask(result, viz_name, leap_type_name)
1254
+ except Exception as e:
1255
+ logger.debug(f"visualizer warning check failed for '{viz_name}': {e}")
1256
+
1257
+
1094
1258
  def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
1095
1259
  heatmap_function: Optional[Callable[..., npt.NDArray[np.float32]]] = None,
1096
1260
  connects_to=None):
@@ -1149,6 +1313,9 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
1149
1313
  (f'{user_function.__name__}() validation failed: '
1150
1314
  f'The return type should be {result_type_map[visualizer_type]}. Got {type(result)}.')
1151
1315
 
1316
+ if not _call_from_tl_platform:
1317
+ _emit_visualizer_warnings(result, name, visualizer_type)
1318
+
1152
1319
  @functools.wraps(user_function)
1153
1320
  def inner_without_validate(*args, **kwargs):
1154
1321
  global _called_from_inside_tl_decorator
@@ -2082,7 +2249,7 @@ def tensorleap_status_table():
2082
2249
  if not data and not stored:
2083
2250
  return
2084
2251
 
2085
- print("\nWarnings (Default use. It is recommended to set values explicitly):")
2252
+ print("\nWarnings:")
2086
2253
  for param_name in sorted(data.keys()):
2087
2254
  default_value = data[param_name]["default_value"]
2088
2255
  funcs = ", ".join(sorted(data[param_name]["funcs"]))
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: code-loader
3
- Version: 1.0.184.dev4
3
+ Version: 1.0.184.dev5
4
4
  Summary:
5
- Home-page: https://github.com/tensorleap/code-loader
6
5
  License: MIT
7
6
  Author: dorhar
8
7
  Author-email: doron.harnoy@tensorleap.ai
@@ -20,6 +19,7 @@ Requires-Dist: numpy (>=2.3.2,<3.0.0) ; python_version >= "3.11" and python_vers
20
19
  Requires-Dist: psutil (>=5.9.5,<6.0.0)
21
20
  Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
22
21
  Requires-Dist: requests (>=2.32.3,<3.0.0)
22
+ Project-URL: Homepage, https://github.com/tensorleap/code-loader
23
23
  Project-URL: Repository, https://github.com/tensorleap/code-loader
24
24
  Description-Content-Type: text/markdown
25
25
 
@@ -1,4 +1,3 @@
1
- LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
2
1
  code_loader/__init__.py,sha256=outxRQ0M-zMfV0QGVJmAed5qWfRmyD0TV6-goEGAzBw,406
3
2
  code_loader/contract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
3
  code_loader/contract/datasetclasses.py,sha256=RYZcnX7vLMYhyQtCbX2PscVFNAYULxgAA9U4DRRfLqA,10456
@@ -22,7 +21,7 @@ code_loader/experiment_api/utils.py,sha256=XZHtxge12TS4H4-8PjV3sKuhp8Ud6ojAiIzTZ
22
21
  code_loader/experiment_api/workingspace_config_utils.py,sha256=DLzXQCg4dgTV_YgaSbeTVzq-2ja_SQw4zi7LXwKL9cY,990
23
22
  code_loader/inner_leap_binder/__init__.py,sha256=koOlJyMNYzGbEsoIbXathSmQ-L38N_pEXH_HvL7beXU,99
24
23
  code_loader/inner_leap_binder/leapbinder.py,sha256=XLYYcV50qjMvoC1S6WW0tLBch_0g5gl1UyHiVSWYbvg,40491
25
- code_loader/inner_leap_binder/leapbinder_decorators.py,sha256=YlK51b5Ryo396f7tOA7Ole3vYCLs3f5ZLm2qDQ9K1NE,105781
24
+ code_loader/inner_leap_binder/leapbinder_decorators.py,sha256=3kcH5xeZsOGnGtmZze3fUxpVBIVRsLiVpx4v9qzTMIM,114805
26
25
  code_loader/leaploader.py,sha256=K9Q5kiCZ_A2GkS5qOEantAMvWGaz3bmO1X8buXDSpgg,44682
27
26
  code_loader/leaploaderbase.py,sha256=l36qDA00GhZEG5NLKpEtAXgWJA-UQQIhNFGxywK7mUA,6530
28
27
  code_loader/mixpanel_tracker.py,sha256=rNwRmFifNbdUoqLQvvhhgpKczWpWiEmd8MfyJe27sxw,9131
@@ -32,7 +31,7 @@ code_loader/plot_functions/visualize.py,sha256=gsBAYYkwMh7jIpJeDMPS8G4CW-pxwx6Lz
32
31
  code_loader/utils.py,sha256=YecipkdTA-VcE9F0RQcY9cFnY8P3AksPnHM2Db7xUSk,3972
33
32
  code_loader/visualizers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
33
  code_loader/visualizers/default_visualizers.py,sha256=onRnLE_TXfgLN4o52hQIOOhUcFexGlqJ3xSpQDVLuZM,2604
35
- code_loader-1.0.184.dev4.dist-info/LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
36
- code_loader-1.0.184.dev4.dist-info/METADATA,sha256=t_BqhlREnawOv6Y-bEqGgefwtLGwg6hmVvdYIaKnzLI,1095
37
- code_loader-1.0.184.dev4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
38
- code_loader-1.0.184.dev4.dist-info/RECORD,,
34
+ code_loader-1.0.184.dev5.dist-info/LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
35
+ code_loader-1.0.184.dev5.dist-info/METADATA,sha256=83dAfYcw1wqEAn7mzBjIYBG4xCZZBJNESjAzXLcr_ks,1107
36
+ code_loader-1.0.184.dev5.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
37
+ code_loader-1.0.184.dev5.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2021 TensorLeap
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
File without changes