supervisely 6.73.452__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.
- supervisely/__init__.py +25 -1
- supervisely/annotation/annotation.py +8 -2
- supervisely/annotation/json_geometries_map.py +13 -12
- supervisely/api/annotation_api.py +6 -3
- supervisely/api/api.py +2 -0
- supervisely/api/app_api.py +10 -1
- supervisely/api/dataset_api.py +74 -12
- supervisely/api/entities_collection_api.py +10 -0
- supervisely/api/entity_annotation/figure_api.py +28 -0
- supervisely/api/entity_annotation/object_api.py +3 -3
- supervisely/api/entity_annotation/tag_api.py +63 -12
- supervisely/api/guides_api.py +210 -0
- supervisely/api/image_api.py +4 -0
- supervisely/api/labeling_job_api.py +83 -1
- supervisely/api/labeling_queue_api.py +33 -7
- supervisely/api/module_api.py +5 -0
- supervisely/api/project_api.py +71 -26
- supervisely/api/storage_api.py +3 -1
- supervisely/api/task_api.py +13 -2
- supervisely/api/team_api.py +4 -3
- supervisely/api/video/video_annotation_api.py +119 -3
- supervisely/api/video/video_api.py +65 -14
- supervisely/app/__init__.py +1 -1
- supervisely/app/content.py +23 -7
- supervisely/app/development/development.py +18 -2
- supervisely/app/fastapi/__init__.py +1 -0
- supervisely/app/fastapi/custom_static_files.py +1 -1
- supervisely/app/fastapi/multi_user.py +105 -0
- supervisely/app/fastapi/subapp.py +88 -42
- supervisely/app/fastapi/websocket.py +77 -9
- supervisely/app/singleton.py +21 -0
- supervisely/app/v1/app_service.py +18 -2
- supervisely/app/v1/constants.py +7 -1
- supervisely/app/widgets/__init__.py +6 -0
- supervisely/app/widgets/activity_feed/__init__.py +0 -0
- supervisely/app/widgets/activity_feed/activity_feed.py +239 -0
- supervisely/app/widgets/activity_feed/style.css +78 -0
- supervisely/app/widgets/activity_feed/template.html +22 -0
- supervisely/app/widgets/card/card.py +20 -0
- supervisely/app/widgets/classes_list_selector/classes_list_selector.py +121 -9
- supervisely/app/widgets/classes_list_selector/template.html +60 -93
- supervisely/app/widgets/classes_mapping/classes_mapping.py +13 -12
- supervisely/app/widgets/classes_table/classes_table.py +1 -0
- supervisely/app/widgets/deploy_model/deploy_model.py +56 -35
- supervisely/app/widgets/ecosystem_model_selector/ecosystem_model_selector.py +1 -1
- supervisely/app/widgets/experiment_selector/experiment_selector.py +8 -0
- supervisely/app/widgets/fast_table/fast_table.py +184 -60
- supervisely/app/widgets/fast_table/template.html +1 -1
- supervisely/app/widgets/heatmap/__init__.py +0 -0
- supervisely/app/widgets/heatmap/heatmap.py +564 -0
- supervisely/app/widgets/heatmap/script.js +533 -0
- supervisely/app/widgets/heatmap/style.css +233 -0
- supervisely/app/widgets/heatmap/template.html +21 -0
- supervisely/app/widgets/modal/__init__.py +0 -0
- supervisely/app/widgets/modal/modal.py +198 -0
- supervisely/app/widgets/modal/template.html +10 -0
- supervisely/app/widgets/object_class_view/object_class_view.py +3 -0
- supervisely/app/widgets/radio_tabs/radio_tabs.py +18 -2
- supervisely/app/widgets/radio_tabs/template.html +1 -0
- supervisely/app/widgets/select/select.py +6 -3
- supervisely/app/widgets/select_class/__init__.py +0 -0
- supervisely/app/widgets/select_class/select_class.py +363 -0
- supervisely/app/widgets/select_class/template.html +50 -0
- supervisely/app/widgets/select_cuda/select_cuda.py +22 -0
- supervisely/app/widgets/select_dataset_tree/select_dataset_tree.py +65 -7
- supervisely/app/widgets/select_tag/__init__.py +0 -0
- supervisely/app/widgets/select_tag/select_tag.py +352 -0
- supervisely/app/widgets/select_tag/template.html +64 -0
- supervisely/app/widgets/select_team/select_team.py +37 -4
- supervisely/app/widgets/select_team/template.html +4 -5
- supervisely/app/widgets/select_user/__init__.py +0 -0
- supervisely/app/widgets/select_user/select_user.py +270 -0
- supervisely/app/widgets/select_user/template.html +13 -0
- supervisely/app/widgets/select_workspace/select_workspace.py +59 -10
- supervisely/app/widgets/select_workspace/template.html +9 -12
- supervisely/app/widgets/table/table.py +68 -13
- supervisely/app/widgets/tree_select/tree_select.py +2 -0
- supervisely/aug/aug.py +6 -2
- supervisely/convert/base_converter.py +1 -0
- supervisely/convert/converter.py +2 -2
- supervisely/convert/image/image_converter.py +3 -1
- supervisely/convert/image/image_helper.py +48 -4
- supervisely/convert/image/label_studio/label_studio_converter.py +2 -0
- supervisely/convert/image/medical2d/medical2d_helper.py +2 -24
- supervisely/convert/image/multispectral/multispectral_converter.py +6 -0
- supervisely/convert/image/pascal_voc/pascal_voc_converter.py +8 -5
- supervisely/convert/image/pascal_voc/pascal_voc_helper.py +7 -0
- supervisely/convert/pointcloud/kitti_3d/kitti_3d_converter.py +33 -3
- supervisely/convert/pointcloud/kitti_3d/kitti_3d_helper.py +12 -5
- supervisely/convert/pointcloud/las/las_converter.py +13 -1
- supervisely/convert/pointcloud/las/las_helper.py +110 -11
- supervisely/convert/pointcloud/nuscenes_conv/nuscenes_converter.py +27 -16
- supervisely/convert/pointcloud/pointcloud_converter.py +91 -3
- supervisely/convert/pointcloud_episodes/nuscenes_conv/nuscenes_converter.py +58 -22
- supervisely/convert/pointcloud_episodes/nuscenes_conv/nuscenes_helper.py +21 -47
- supervisely/convert/video/__init__.py +1 -0
- supervisely/convert/video/multi_view/__init__.py +0 -0
- supervisely/convert/video/multi_view/multi_view.py +543 -0
- supervisely/convert/video/sly/sly_video_converter.py +359 -3
- supervisely/convert/video/video_converter.py +22 -2
- supervisely/convert/volume/dicom/dicom_converter.py +13 -5
- supervisely/convert/volume/dicom/dicom_helper.py +30 -18
- supervisely/geometry/constants.py +1 -0
- supervisely/geometry/geometry.py +4 -0
- supervisely/geometry/helpers.py +5 -1
- supervisely/geometry/oriented_bbox.py +676 -0
- supervisely/geometry/rectangle.py +2 -1
- supervisely/io/env.py +76 -1
- supervisely/io/fs.py +21 -0
- supervisely/nn/benchmark/base_evaluator.py +104 -11
- supervisely/nn/benchmark/instance_segmentation/evaluator.py +1 -8
- supervisely/nn/benchmark/object_detection/evaluator.py +20 -4
- supervisely/nn/benchmark/object_detection/vis_metrics/pr_curve.py +10 -5
- supervisely/nn/benchmark/semantic_segmentation/evaluator.py +34 -16
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/confusion_matrix.py +1 -1
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/frequently_confused.py +1 -1
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/overview.py +1 -1
- supervisely/nn/benchmark/visualization/evaluation_result.py +66 -4
- supervisely/nn/inference/cache.py +43 -18
- supervisely/nn/inference/gui/serving_gui_template.py +5 -2
- supervisely/nn/inference/inference.py +795 -199
- supervisely/nn/inference/inference_request.py +42 -9
- supervisely/nn/inference/predict_app/gui/classes_selector.py +83 -12
- supervisely/nn/inference/predict_app/gui/gui.py +676 -488
- supervisely/nn/inference/predict_app/gui/input_selector.py +205 -26
- supervisely/nn/inference/predict_app/gui/model_selector.py +2 -4
- supervisely/nn/inference/predict_app/gui/output_selector.py +46 -6
- supervisely/nn/inference/predict_app/gui/settings_selector.py +756 -59
- supervisely/nn/inference/predict_app/gui/tags_selector.py +1 -1
- supervisely/nn/inference/predict_app/gui/utils.py +236 -119
- supervisely/nn/inference/predict_app/predict_app.py +2 -2
- supervisely/nn/inference/session.py +43 -35
- supervisely/nn/inference/tracking/bbox_tracking.py +113 -34
- supervisely/nn/inference/tracking/tracker_interface.py +7 -2
- supervisely/nn/inference/uploader.py +139 -12
- supervisely/nn/live_training/__init__.py +7 -0
- supervisely/nn/live_training/api_server.py +111 -0
- supervisely/nn/live_training/artifacts_utils.py +243 -0
- supervisely/nn/live_training/checkpoint_utils.py +229 -0
- supervisely/nn/live_training/dynamic_sampler.py +44 -0
- supervisely/nn/live_training/helpers.py +14 -0
- supervisely/nn/live_training/incremental_dataset.py +146 -0
- supervisely/nn/live_training/live_training.py +497 -0
- supervisely/nn/live_training/loss_plateau_detector.py +111 -0
- supervisely/nn/live_training/request_queue.py +52 -0
- supervisely/nn/model/model_api.py +9 -0
- supervisely/nn/prediction_dto.py +12 -1
- supervisely/nn/tracker/base_tracker.py +11 -1
- supervisely/nn/tracker/botsort/botsort_config.yaml +0 -1
- supervisely/nn/tracker/botsort/tracker/mc_bot_sort.py +7 -4
- supervisely/nn/tracker/botsort_tracker.py +94 -65
- supervisely/nn/tracker/visualize.py +87 -90
- supervisely/nn/training/gui/classes_selector.py +16 -1
- supervisely/nn/training/train_app.py +28 -29
- supervisely/project/data_version.py +115 -51
- supervisely/project/download.py +1 -1
- supervisely/project/pointcloud_episode_project.py +37 -8
- supervisely/project/pointcloud_project.py +30 -2
- supervisely/project/project.py +14 -2
- supervisely/project/project_meta.py +27 -1
- supervisely/project/project_settings.py +32 -18
- supervisely/project/versioning/__init__.py +1 -0
- supervisely/project/versioning/common.py +20 -0
- supervisely/project/versioning/schema_fields.py +35 -0
- supervisely/project/versioning/video_schema.py +221 -0
- supervisely/project/versioning/volume_schema.py +87 -0
- supervisely/project/video_project.py +717 -15
- supervisely/project/volume_project.py +623 -5
- supervisely/template/experiment/experiment.html.jinja +4 -4
- supervisely/template/experiment/experiment_generator.py +14 -21
- supervisely/template/live_training/__init__.py +0 -0
- supervisely/template/live_training/header.html.jinja +96 -0
- supervisely/template/live_training/live_training.html.jinja +51 -0
- supervisely/template/live_training/live_training_generator.py +464 -0
- supervisely/template/live_training/sly-style.css +402 -0
- supervisely/template/live_training/template.html.jinja +18 -0
- supervisely/versions.json +28 -26
- supervisely/video/sampling.py +39 -20
- supervisely/video/video.py +40 -11
- supervisely/video_annotation/video_object.py +29 -4
- supervisely/volume/stl_converter.py +2 -0
- supervisely/worker_api/agent_rpc.py +24 -1
- supervisely/worker_api/rpc_servicer.py +31 -7
- {supervisely-6.73.452.dist-info → supervisely-6.73.513.dist-info}/METADATA +56 -39
- {supervisely-6.73.452.dist-info → supervisely-6.73.513.dist-info}/RECORD +189 -142
- {supervisely-6.73.452.dist-info → supervisely-6.73.513.dist-info}/WHEEL +1 -1
- {supervisely-6.73.452.dist-info → supervisely-6.73.513.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.452.dist-info → supervisely-6.73.513.dist-info/licenses}/LICENSE +0 -0
- {supervisely-6.73.452.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
|
|
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,8 @@ 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()
|
|
50
48
|
self._progress_log_interval = 5.0
|
|
51
49
|
self._last_progress_report_time = 0
|
|
52
50
|
self.progress = Progress(
|
|
@@ -60,6 +58,8 @@ class InferenceRequest:
|
|
|
60
58
|
self._updated_at = self._created_at
|
|
61
59
|
self._finished = False
|
|
62
60
|
|
|
61
|
+
self.tracker = None
|
|
62
|
+
|
|
63
63
|
self.global_progress = None
|
|
64
64
|
self.global_progress_total = 1
|
|
65
65
|
self.global_progress_current = 0
|
|
@@ -97,10 +97,16 @@ class InferenceRequest:
|
|
|
97
97
|
def add_results(self, results: List[Dict]):
|
|
98
98
|
with self._lock:
|
|
99
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()
|
|
100
105
|
self._updated()
|
|
101
106
|
|
|
102
107
|
def pop_pending_results(self, n: int = None):
|
|
103
108
|
with self._lock:
|
|
109
|
+
self.continue_if_paused()
|
|
104
110
|
if len(self._pending_results) == 0:
|
|
105
111
|
return []
|
|
106
112
|
if n is None:
|
|
@@ -176,6 +182,27 @@ class InferenceRequest:
|
|
|
176
182
|
def is_stopped(self):
|
|
177
183
|
return self._stopped.is_set()
|
|
178
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
|
+
|
|
179
206
|
def is_finished(self):
|
|
180
207
|
return self._finished
|
|
181
208
|
|
|
@@ -212,6 +239,7 @@ class InferenceRequest:
|
|
|
212
239
|
"exception": self.exception_json(),
|
|
213
240
|
"is_inferring": self.is_inferring(),
|
|
214
241
|
"stopped": self.is_stopped(),
|
|
242
|
+
"paused": self.is_paused(),
|
|
215
243
|
"finished": self._finished,
|
|
216
244
|
"created_at": self._created_at,
|
|
217
245
|
"updated_at": self._updated_at,
|
|
@@ -365,6 +393,11 @@ class InferenceRequestsManager:
|
|
|
365
393
|
inference_request = self._inference_requests.get(inference_request_uuid)
|
|
366
394
|
if inference_request is None:
|
|
367
395
|
continue
|
|
396
|
+
if (
|
|
397
|
+
inference_request.is_paused()
|
|
398
|
+
and inference_request.paused_for() < InferenceRequest.PAUSE_SLEEP_MAX_WAIT
|
|
399
|
+
):
|
|
400
|
+
continue
|
|
368
401
|
if inference_request.is_expired():
|
|
369
402
|
self.remove(inference_request_uuid)
|
|
370
403
|
logger.debug(f"Expired inference request {inference_request_uuid} was deleted")
|
|
@@ -1,10 +1,50 @@
|
|
|
1
|
-
from typing import
|
|
2
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
116
|
+
self.classes_table.select_rows_by_value("class", classes)
|
|
64
117
|
|
|
65
118
|
def select_all_classes(self) -> None:
|
|
66
|
-
self.classes_table.
|
|
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.
|
|
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()
|