supervisely 6.73.438__py3-none-any.whl → 6.73.513__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.
Files changed (203) hide show
  1. supervisely/__init__.py +137 -1
  2. supervisely/_utils.py +81 -0
  3. supervisely/annotation/annotation.py +8 -2
  4. supervisely/annotation/json_geometries_map.py +14 -11
  5. supervisely/annotation/label.py +80 -3
  6. supervisely/api/annotation_api.py +14 -11
  7. supervisely/api/api.py +59 -38
  8. supervisely/api/app_api.py +11 -2
  9. supervisely/api/dataset_api.py +74 -12
  10. supervisely/api/entities_collection_api.py +10 -0
  11. supervisely/api/entity_annotation/figure_api.py +52 -4
  12. supervisely/api/entity_annotation/object_api.py +3 -3
  13. supervisely/api/entity_annotation/tag_api.py +63 -12
  14. supervisely/api/guides_api.py +210 -0
  15. supervisely/api/image_api.py +72 -1
  16. supervisely/api/labeling_job_api.py +83 -1
  17. supervisely/api/labeling_queue_api.py +33 -7
  18. supervisely/api/module_api.py +9 -0
  19. supervisely/api/project_api.py +71 -26
  20. supervisely/api/storage_api.py +3 -1
  21. supervisely/api/task_api.py +13 -2
  22. supervisely/api/team_api.py +4 -3
  23. supervisely/api/video/video_annotation_api.py +119 -3
  24. supervisely/api/video/video_api.py +65 -14
  25. supervisely/api/video/video_figure_api.py +24 -11
  26. supervisely/app/__init__.py +1 -1
  27. supervisely/app/content.py +23 -7
  28. supervisely/app/development/development.py +18 -2
  29. supervisely/app/fastapi/__init__.py +1 -0
  30. supervisely/app/fastapi/custom_static_files.py +1 -1
  31. supervisely/app/fastapi/multi_user.py +105 -0
  32. supervisely/app/fastapi/subapp.py +88 -42
  33. supervisely/app/fastapi/websocket.py +77 -9
  34. supervisely/app/singleton.py +21 -0
  35. supervisely/app/v1/app_service.py +18 -2
  36. supervisely/app/v1/constants.py +7 -1
  37. supervisely/app/widgets/__init__.py +6 -0
  38. supervisely/app/widgets/activity_feed/__init__.py +0 -0
  39. supervisely/app/widgets/activity_feed/activity_feed.py +239 -0
  40. supervisely/app/widgets/activity_feed/style.css +78 -0
  41. supervisely/app/widgets/activity_feed/template.html +22 -0
  42. supervisely/app/widgets/card/card.py +20 -0
  43. supervisely/app/widgets/classes_list_selector/classes_list_selector.py +121 -9
  44. supervisely/app/widgets/classes_list_selector/template.html +60 -93
  45. supervisely/app/widgets/classes_mapping/classes_mapping.py +13 -12
  46. supervisely/app/widgets/classes_table/classes_table.py +1 -0
  47. supervisely/app/widgets/deploy_model/deploy_model.py +56 -35
  48. supervisely/app/widgets/dialog/dialog.py +12 -0
  49. supervisely/app/widgets/dialog/template.html +2 -1
  50. supervisely/app/widgets/ecosystem_model_selector/ecosystem_model_selector.py +1 -1
  51. supervisely/app/widgets/experiment_selector/experiment_selector.py +8 -0
  52. supervisely/app/widgets/fast_table/fast_table.py +184 -60
  53. supervisely/app/widgets/fast_table/template.html +1 -1
  54. supervisely/app/widgets/heatmap/__init__.py +0 -0
  55. supervisely/app/widgets/heatmap/heatmap.py +564 -0
  56. supervisely/app/widgets/heatmap/script.js +533 -0
  57. supervisely/app/widgets/heatmap/style.css +233 -0
  58. supervisely/app/widgets/heatmap/template.html +21 -0
  59. supervisely/app/widgets/modal/__init__.py +0 -0
  60. supervisely/app/widgets/modal/modal.py +198 -0
  61. supervisely/app/widgets/modal/template.html +10 -0
  62. supervisely/app/widgets/object_class_view/object_class_view.py +3 -0
  63. supervisely/app/widgets/radio_tabs/radio_tabs.py +18 -2
  64. supervisely/app/widgets/radio_tabs/template.html +1 -0
  65. supervisely/app/widgets/select/select.py +6 -3
  66. supervisely/app/widgets/select_class/__init__.py +0 -0
  67. supervisely/app/widgets/select_class/select_class.py +363 -0
  68. supervisely/app/widgets/select_class/template.html +50 -0
  69. supervisely/app/widgets/select_cuda/select_cuda.py +22 -0
  70. supervisely/app/widgets/select_dataset_tree/select_dataset_tree.py +65 -7
  71. supervisely/app/widgets/select_tag/__init__.py +0 -0
  72. supervisely/app/widgets/select_tag/select_tag.py +352 -0
  73. supervisely/app/widgets/select_tag/template.html +64 -0
  74. supervisely/app/widgets/select_team/select_team.py +37 -4
  75. supervisely/app/widgets/select_team/template.html +4 -5
  76. supervisely/app/widgets/select_user/__init__.py +0 -0
  77. supervisely/app/widgets/select_user/select_user.py +270 -0
  78. supervisely/app/widgets/select_user/template.html +13 -0
  79. supervisely/app/widgets/select_workspace/select_workspace.py +59 -10
  80. supervisely/app/widgets/select_workspace/template.html +9 -12
  81. supervisely/app/widgets/table/table.py +68 -13
  82. supervisely/app/widgets/tree_select/tree_select.py +2 -0
  83. supervisely/aug/aug.py +6 -2
  84. supervisely/convert/base_converter.py +1 -0
  85. supervisely/convert/converter.py +2 -2
  86. supervisely/convert/image/csv/csv_converter.py +24 -15
  87. supervisely/convert/image/image_converter.py +3 -1
  88. supervisely/convert/image/image_helper.py +48 -4
  89. supervisely/convert/image/label_studio/label_studio_converter.py +2 -0
  90. supervisely/convert/image/medical2d/medical2d_helper.py +2 -24
  91. supervisely/convert/image/multispectral/multispectral_converter.py +6 -0
  92. supervisely/convert/image/pascal_voc/pascal_voc_converter.py +8 -5
  93. supervisely/convert/image/pascal_voc/pascal_voc_helper.py +7 -0
  94. supervisely/convert/pointcloud/kitti_3d/kitti_3d_converter.py +33 -3
  95. supervisely/convert/pointcloud/kitti_3d/kitti_3d_helper.py +12 -5
  96. supervisely/convert/pointcloud/las/las_converter.py +13 -1
  97. supervisely/convert/pointcloud/las/las_helper.py +110 -11
  98. supervisely/convert/pointcloud/nuscenes_conv/nuscenes_converter.py +27 -16
  99. supervisely/convert/pointcloud/pointcloud_converter.py +91 -3
  100. supervisely/convert/pointcloud_episodes/nuscenes_conv/nuscenes_converter.py +58 -22
  101. supervisely/convert/pointcloud_episodes/nuscenes_conv/nuscenes_helper.py +21 -47
  102. supervisely/convert/video/__init__.py +1 -0
  103. supervisely/convert/video/multi_view/__init__.py +0 -0
  104. supervisely/convert/video/multi_view/multi_view.py +543 -0
  105. supervisely/convert/video/sly/sly_video_converter.py +359 -3
  106. supervisely/convert/video/video_converter.py +24 -4
  107. supervisely/convert/volume/dicom/dicom_converter.py +13 -5
  108. supervisely/convert/volume/dicom/dicom_helper.py +30 -18
  109. supervisely/geometry/constants.py +1 -0
  110. supervisely/geometry/geometry.py +4 -0
  111. supervisely/geometry/helpers.py +5 -1
  112. supervisely/geometry/oriented_bbox.py +676 -0
  113. supervisely/geometry/polyline_3d.py +110 -0
  114. supervisely/geometry/rectangle.py +2 -1
  115. supervisely/io/env.py +76 -1
  116. supervisely/io/fs.py +21 -0
  117. supervisely/nn/benchmark/base_evaluator.py +104 -11
  118. supervisely/nn/benchmark/instance_segmentation/evaluator.py +1 -8
  119. supervisely/nn/benchmark/object_detection/evaluator.py +20 -4
  120. supervisely/nn/benchmark/object_detection/vis_metrics/pr_curve.py +10 -5
  121. supervisely/nn/benchmark/semantic_segmentation/evaluator.py +34 -16
  122. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/confusion_matrix.py +1 -1
  123. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/frequently_confused.py +1 -1
  124. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/overview.py +1 -1
  125. supervisely/nn/benchmark/visualization/evaluation_result.py +66 -4
  126. supervisely/nn/inference/cache.py +43 -18
  127. supervisely/nn/inference/gui/serving_gui_template.py +5 -2
  128. supervisely/nn/inference/inference.py +916 -222
  129. supervisely/nn/inference/inference_request.py +55 -10
  130. supervisely/nn/inference/predict_app/gui/classes_selector.py +83 -12
  131. supervisely/nn/inference/predict_app/gui/gui.py +676 -488
  132. supervisely/nn/inference/predict_app/gui/input_selector.py +205 -26
  133. supervisely/nn/inference/predict_app/gui/model_selector.py +2 -4
  134. supervisely/nn/inference/predict_app/gui/output_selector.py +46 -6
  135. supervisely/nn/inference/predict_app/gui/settings_selector.py +756 -59
  136. supervisely/nn/inference/predict_app/gui/tags_selector.py +1 -1
  137. supervisely/nn/inference/predict_app/gui/utils.py +236 -119
  138. supervisely/nn/inference/predict_app/predict_app.py +2 -2
  139. supervisely/nn/inference/session.py +43 -35
  140. supervisely/nn/inference/tracking/bbox_tracking.py +118 -35
  141. supervisely/nn/inference/tracking/point_tracking.py +5 -1
  142. supervisely/nn/inference/tracking/tracker_interface.py +10 -1
  143. supervisely/nn/inference/uploader.py +139 -12
  144. supervisely/nn/live_training/__init__.py +7 -0
  145. supervisely/nn/live_training/api_server.py +111 -0
  146. supervisely/nn/live_training/artifacts_utils.py +243 -0
  147. supervisely/nn/live_training/checkpoint_utils.py +229 -0
  148. supervisely/nn/live_training/dynamic_sampler.py +44 -0
  149. supervisely/nn/live_training/helpers.py +14 -0
  150. supervisely/nn/live_training/incremental_dataset.py +146 -0
  151. supervisely/nn/live_training/live_training.py +497 -0
  152. supervisely/nn/live_training/loss_plateau_detector.py +111 -0
  153. supervisely/nn/live_training/request_queue.py +52 -0
  154. supervisely/nn/model/model_api.py +9 -0
  155. supervisely/nn/model/prediction.py +2 -1
  156. supervisely/nn/model/prediction_session.py +26 -14
  157. supervisely/nn/prediction_dto.py +19 -1
  158. supervisely/nn/tracker/base_tracker.py +11 -1
  159. supervisely/nn/tracker/botsort/botsort_config.yaml +0 -1
  160. supervisely/nn/tracker/botsort/tracker/mc_bot_sort.py +7 -4
  161. supervisely/nn/tracker/botsort_tracker.py +94 -65
  162. supervisely/nn/tracker/utils.py +4 -5
  163. supervisely/nn/tracker/visualize.py +93 -93
  164. supervisely/nn/training/gui/classes_selector.py +16 -1
  165. supervisely/nn/training/gui/train_val_splits_selector.py +52 -31
  166. supervisely/nn/training/train_app.py +46 -31
  167. supervisely/project/data_version.py +115 -51
  168. supervisely/project/download.py +1 -1
  169. supervisely/project/pointcloud_episode_project.py +37 -8
  170. supervisely/project/pointcloud_project.py +30 -2
  171. supervisely/project/project.py +14 -2
  172. supervisely/project/project_meta.py +27 -1
  173. supervisely/project/project_settings.py +32 -18
  174. supervisely/project/versioning/__init__.py +1 -0
  175. supervisely/project/versioning/common.py +20 -0
  176. supervisely/project/versioning/schema_fields.py +35 -0
  177. supervisely/project/versioning/video_schema.py +221 -0
  178. supervisely/project/versioning/volume_schema.py +87 -0
  179. supervisely/project/video_project.py +717 -15
  180. supervisely/project/volume_project.py +623 -5
  181. supervisely/template/experiment/experiment.html.jinja +4 -4
  182. supervisely/template/experiment/experiment_generator.py +14 -21
  183. supervisely/template/live_training/__init__.py +0 -0
  184. supervisely/template/live_training/header.html.jinja +96 -0
  185. supervisely/template/live_training/live_training.html.jinja +51 -0
  186. supervisely/template/live_training/live_training_generator.py +464 -0
  187. supervisely/template/live_training/sly-style.css +402 -0
  188. supervisely/template/live_training/template.html.jinja +18 -0
  189. supervisely/versions.json +28 -26
  190. supervisely/video/sampling.py +39 -20
  191. supervisely/video/video.py +41 -12
  192. supervisely/video_annotation/video_figure.py +38 -4
  193. supervisely/video_annotation/video_object.py +29 -4
  194. supervisely/volume/stl_converter.py +2 -0
  195. supervisely/worker_api/agent_rpc.py +24 -1
  196. supervisely/worker_api/rpc_servicer.py +31 -7
  197. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/METADATA +58 -40
  198. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/RECORD +203 -155
  199. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/WHEEL +1 -1
  200. supervisely_lib/__init__.py +6 -1
  201. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/entry_points.txt +0 -0
  202. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info/licenses}/LICENSE +0 -0
  203. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/top_level.txt +0 -0
@@ -5,23 +5,19 @@ import time
5
5
  import traceback
6
6
  import uuid
7
7
  from concurrent.futures import Future, ThreadPoolExecutor
8
- from functools import partial, wraps
8
+ from functools import partial
9
9
  from typing import Any, Dict, List, Tuple, Union
10
10
 
11
- from supervisely._utils import rand_str
12
11
  from supervisely.nn.utils import get_gpu_usage, get_ram_usage
13
12
  from supervisely.sly_logger import logger
14
13
  from supervisely.task.progress import Progress
15
14
 
16
15
 
17
- def generate_uuid(self) -> str:
18
- """
19
- Generates a unique UUID for the inference request.
20
- """
21
- return uuid.uuid5(namespace=uuid.NAMESPACE_URL, name=f"{time.time()}-{rand_str(10)}").hex
22
-
23
-
24
16
  class InferenceRequest:
17
+ PAUSE_SLEEP_INTERVAL = 1.0
18
+ PAUSE_SLEEP_MAX_WAIT = 60 * 60 # 1 hour
19
+ PENDING_RESULTS_MAX_SIZE = 500
20
+
25
21
  class Stage:
26
22
  PREPARING = "Preparing model for inference..."
27
23
  INFERENCE = "Running inference..."
@@ -47,6 +43,10 @@ class InferenceRequest:
47
43
  self._final_result = None
48
44
  self._exception = None
49
45
  self._stopped = threading.Event()
46
+ self._paused_time = None
47
+ self._paused = threading.Event()
48
+ self._progress_log_interval = 5.0
49
+ self._last_progress_report_time = 0
50
50
  self.progress = Progress(
51
51
  message=self._stage,
52
52
  total_cnt=1,
@@ -58,6 +58,8 @@ class InferenceRequest:
58
58
  self._updated_at = self._created_at
59
59
  self._finished = False
60
60
 
61
+ self.tracker = None
62
+
61
63
  self.global_progress = None
62
64
  self.global_progress_total = 1
63
65
  self.global_progress_current = 0
@@ -95,10 +97,16 @@ class InferenceRequest:
95
97
  def add_results(self, results: List[Dict]):
96
98
  with self._lock:
97
99
  self._pending_results.extend(results)
100
+ if self.pending_num() >= self.PENDING_RESULTS_MAX_SIZE:
101
+ logger.warning(
102
+ f"Pending results exceeded max size {self.PENDING_RESULTS_MAX_SIZE}, pausing inference request {self._uuid} for {self.PAUSE_SLEEP_MAX_WAIT} seconds."
103
+ )
104
+ self.pause()
98
105
  self._updated()
99
106
 
100
107
  def pop_pending_results(self, n: int = None):
101
108
  with self._lock:
109
+ self.continue_if_paused()
102
110
  if len(self._pending_results) == 0:
103
111
  return []
104
112
  if n is None:
@@ -135,9 +143,19 @@ class InferenceRequest:
135
143
  )
136
144
  self._updated()
137
145
 
146
+ def set_progress_log_interval(self, interval: float):
147
+ self._progress_log_interval = interval
148
+
138
149
  def done(self, n=1):
139
150
  with self._lock:
140
- self.progress.iters_done_report(n)
151
+ if (
152
+ self._progress_log_interval is None
153
+ or time.monotonic() - self._last_progress_report_time > self._progress_log_interval
154
+ ) or (self.progress.current + n >= self.progress.total):
155
+ self.progress.iters_done_report(n)
156
+ self._last_progress_report_time = time.monotonic()
157
+ else:
158
+ self.progress.iters_done(n)
141
159
  if self._stage == InferenceRequest.Stage.INFERENCE:
142
160
  self.global_progress_current += n
143
161
  if self.manager is not None:
@@ -164,6 +182,27 @@ class InferenceRequest:
164
182
  def is_stopped(self):
165
183
  return self._stopped.is_set()
166
184
 
185
+ def pause(self):
186
+ self._paused.set()
187
+ self._paused_time = time.monotonic()
188
+ self._updated()
189
+
190
+ def is_paused(self):
191
+ return self._paused.is_set()
192
+
193
+ def continue_if_paused(self):
194
+ if not self.is_paused():
195
+ return
196
+ logger.debug(f"Continuing paused inference request {self._uuid}")
197
+ self._paused.clear()
198
+ self._paused_time = None
199
+ self._updated()
200
+
201
+ def paused_for(self):
202
+ if not self.is_paused():
203
+ return 0
204
+ return time.monotonic() - self._paused_time
205
+
167
206
  def is_finished(self):
168
207
  return self._finished
169
208
 
@@ -200,6 +239,7 @@ class InferenceRequest:
200
239
  "exception": self.exception_json(),
201
240
  "is_inferring": self.is_inferring(),
202
241
  "stopped": self.is_stopped(),
242
+ "paused": self.is_paused(),
203
243
  "finished": self._finished,
204
244
  "created_at": self._created_at,
205
245
  "updated_at": self._updated_at,
@@ -353,6 +393,11 @@ class InferenceRequestsManager:
353
393
  inference_request = self._inference_requests.get(inference_request_uuid)
354
394
  if inference_request is None:
355
395
  continue
396
+ if (
397
+ inference_request.is_paused()
398
+ and inference_request.paused_for() < InferenceRequest.PAUSE_SLEEP_MAX_WAIT
399
+ ):
400
+ continue
356
401
  if inference_request.is_expired():
357
402
  self.remove(inference_request_uuid)
358
403
  logger.debug(f"Expired inference request {inference_request_uuid} was deleted")
@@ -1,10 +1,50 @@
1
- from typing import Dict, Any
2
- from supervisely.app.widgets import Button, Card, ClassesTable, Container, Text
3
-
4
-
1
+ from typing import Any, Dict
2
+
3
+ import pandas as pd
4
+
5
+ from supervisely.app.widgets import (
6
+ Button,
7
+ Card,
8
+ ClassesTable,
9
+ Container,
10
+ FastTable,
11
+ Text,
12
+ )
13
+ from supervisely.geometry.any_geometry import AnyGeometry
14
+ from supervisely.geometry.bitmap import Bitmap
15
+ from supervisely.geometry.cuboid import Cuboid
16
+ from supervisely.geometry.cuboid_3d import Cuboid3d
17
+ from supervisely.geometry.geometry import Geometry
18
+ from supervisely.geometry.graph import GraphNodes
19
+ from supervisely.geometry.multichannel_bitmap import MultichannelBitmap
20
+ from supervisely.geometry.point import Point
21
+ from supervisely.geometry.point_3d import Point3d
22
+ from supervisely.geometry.pointcloud import Pointcloud
23
+ from supervisely.geometry.polygon import Polygon
24
+ from supervisely.geometry.polyline import Polyline
25
+ from supervisely.geometry.rectangle import Rectangle
26
+ from supervisely.geometry.oriented_bbox import OrientedBBox
27
+ from supervisely.project.project_meta import ProjectMeta
28
+
29
+ type_to_zmdi_icon = {
30
+ AnyGeometry: "zmdi zmdi-shape",
31
+ Rectangle: "zmdi zmdi-crop-din", # "zmdi zmdi-square-o"
32
+ # sly.Polygon: "icons8-polygon", # "zmdi zmdi-edit"
33
+ Polygon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAB6klEQVRYhe2Wuy8EURTGf+u5VESNXq2yhYZCoeBv8RcI1i6NVUpsoVCKkHjUGlFTiYb1mFmh2MiKjVXMudmb3cPOzB0VXzKZm5k53/nmvO6Ff4RHD5AD7gFP1l3Kd11AHvCBEpAVW2esAvWmK6t8l1O+W0lCQEnIJoAZxUnzNQNkZF36jrQjgoA+uaciCgc9VaExBOyh/6WWAi1VhbjOJ4FbIXkBtgkK0BNHnYqNKUIPeBPbKyDdzpld5T6wD9SE4AwYjfEDaXFeFzE/doUWuhqwiFsOCwqv2hV2lU/L+sHBscGTxdvSFVoXpAjCZdauMHVic6ndl6U1VBsJCFhTeNUU9IiIEo3qvQYGHAV0AyfC5wNLhKipXuBCjA5wT8WxcM1FMRoBymK44CjAE57hqIazwCfwQdARcXa3UXHuRXVucIjb7jYvNkdxBZg0TBFid7PQTRAtX2xOiXkuMAMqYwkIE848rZFbjyNAmw9bIeweaZ2A5TgC7PnwKkTPtN+cTOrsyN3FEWAjRTAX6sA5ek77gSL6+WHZVQDAIHAjhJtN78aAS3lXAXYIivBOnCdyOAUYB6o0xqsvziry7FLE/Cp20cNcJEjDr8MUmVOVRzkVN+Nd7vZGVXXgiwxtPiRS5WFhz4fEq/zv4AvToMn7vCn3eAAAAABJRU5ErkJggg==",
34
+ Bitmap: "zmdi zmdi-brush",
35
+ Polyline: "zmdi zmdi-gesture",
36
+ Point: "zmdi zmdi-dot-circle-alt",
37
+ Cuboid: "zmdi zmdi-ungroup", #
38
+ GraphNodes: "zmdi zmdi-grain",
39
+ Cuboid3d: "zmdi zmdi-codepen",
40
+ Pointcloud: "zmdi zmdi-cloud-outline", # "zmdi zmdi-border-clear"
41
+ MultichannelBitmap: "zmdi zmdi-layers", # "zmdi zmdi-collection-item"
42
+ Point3d: "zmdi zmdi-filter-center-focus", # "zmdi zmdi-select-all"
43
+ OrientedBBox: "zmdi zmdi-rotate-cw",
44
+ }
5
45
  class ClassesSelector:
6
- title = "Classes Selector"
7
- description = "Select classes that will be used for inference"
46
+ title = "Classes"
47
+ description = "Select classes that will be used for inference. This classes are defined by the deployed model"
8
48
  lock_message = "Select previous step to unlock"
9
49
 
10
50
  def __init__(self):
@@ -24,7 +64,9 @@ class ClassesSelector:
24
64
  # -------------------------------- #
25
65
 
26
66
  # Classes
27
- self.classes_table = ClassesTable()
67
+ columns = ["class", "shape"]
68
+ self.classes_table = FastTable(columns=columns, page_size=100, is_selectable=True)
69
+ # self.classes_table = ClassesTable()
28
70
  self.classes_table.hide()
29
71
  # Add widgets to display ------------ #
30
72
  self.display_widgets.extend([self.classes_table])
@@ -45,25 +87,36 @@ class ClassesSelector:
45
87
  content=self.container,
46
88
  lock_message=self.lock_message,
47
89
  )
48
- self.card.lock()
49
90
  # -------------------------------- #
50
91
 
92
+ def lock(self):
93
+ self.card.lock()
94
+ self.classes_table.hide()
95
+ self.validator_text.hide()
96
+
97
+ def unlock(self):
98
+ self.card.unlock()
99
+ self.classes_table.show()
100
+
51
101
  @property
52
102
  def widgets_to_disable(self) -> list:
53
103
  return [self.classes_table]
54
104
 
105
+ def set_project_meta(self, project_meta) -> None:
106
+ self._update_meta(project_meta)
107
+
55
108
  def load_from_json(self, data: Dict[str, Any]) -> None:
56
109
  if "classes" in data:
57
110
  self.set_classes(data["classes"])
58
111
 
59
112
  def get_selected_classes(self) -> list:
60
- return self.classes_table.get_selected_classes()
113
+ return [row.row[0] for row in self.classes_table.get_selected_rows()]
61
114
 
62
115
  def set_classes(self, classes) -> None:
63
- self.classes_table.select_classes(classes)
116
+ self.classes_table.select_rows_by_value("class", classes)
64
117
 
65
118
  def select_all_classes(self) -> None:
66
- self.classes_table.select_all()
119
+ self.classes_table.select_rows(list(range(len(self.classes_table._rows_total))))
67
120
 
68
121
  def get_settings(self) -> Dict[str, Any]:
69
122
  return {"classes": self.get_selected_classes()}
@@ -73,7 +126,7 @@ class ClassesSelector:
73
126
  return True
74
127
 
75
128
  self.validator_text.hide()
76
- selected_classes = self.classes_table.get_selected_classes()
129
+ selected_classes = self.get_selected_classes()
77
130
  n_classes = len(selected_classes)
78
131
 
79
132
  if n_classes == 0:
@@ -89,3 +142,21 @@ class ClassesSelector:
89
142
  self.validator_text.set(text=". ".join(message_parts), status=status)
90
143
  self.validator_text.show()
91
144
  return is_valid
145
+
146
+ def _update_meta(self, project_meta: ProjectMeta) -> None:
147
+ table_data = []
148
+ for obj_class in project_meta.obj_classes:
149
+ table_line = []
150
+ name = obj_class.name
151
+ icon = type_to_zmdi_icon[AnyGeometry]
152
+ icon = type_to_zmdi_icon.get(obj_class.geometry_type, icon)
153
+ shape = obj_class.geometry_type.geometry_name().lower()
154
+ if shape == "graph":
155
+ shape = "graph (keypoints)"
156
+ table_line = [name, shape]
157
+ table_data.append(table_line)
158
+ self._table_data = table_data
159
+ if self._table_data:
160
+ self.classes_table.read_pandas(pd.DataFrame(self._table_data))
161
+ else:
162
+ self.classes_table.clear()