supervisely 6.73.251__py3-none-any.whl → 6.73.253__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 supervisely might be problematic. Click here for more details.
- supervisely/api/dataset_api.py +17 -1
- supervisely/api/project_api.py +4 -1
- supervisely/api/volume/volume_annotation_api.py +7 -4
- supervisely/app/widgets/experiment_selector/experiment_selector.py +13 -3
- supervisely/nn/artifacts/artifacts.py +92 -1
- supervisely/nn/artifacts/detectron2.py +1 -0
- supervisely/nn/artifacts/mmclassification.py +1 -0
- supervisely/nn/artifacts/mmdetection.py +2 -0
- supervisely/nn/artifacts/mmsegmentation.py +1 -0
- supervisely/nn/artifacts/ritm.py +1 -0
- supervisely/nn/artifacts/rtdetr.py +1 -0
- supervisely/nn/artifacts/unet.py +1 -0
- supervisely/nn/artifacts/utils.py +50 -0
- supervisely/nn/artifacts/yolov5.py +2 -0
- supervisely/nn/artifacts/yolov8.py +1 -0
- supervisely/nn/experiments.py +13 -7
- supervisely/nn/training/gui/model_selector.py +12 -1
- {supervisely-6.73.251.dist-info → supervisely-6.73.253.dist-info}/METADATA +1 -1
- {supervisely-6.73.251.dist-info → supervisely-6.73.253.dist-info}/RECORD +23 -22
- {supervisely-6.73.251.dist-info → supervisely-6.73.253.dist-info}/LICENSE +0 -0
- {supervisely-6.73.251.dist-info → supervisely-6.73.253.dist-info}/WHEEL +0 -0
- {supervisely-6.73.251.dist-info → supervisely-6.73.253.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.251.dist-info → supervisely-6.73.253.dist-info}/top_level.txt +0 -0
supervisely/api/dataset_api.py
CHANGED
|
@@ -263,6 +263,21 @@ class DatasetApi(UpdateableModule, RemoveableModuleApi):
|
|
|
263
263
|
raise KeyError(f"Dataset with id={id} not found in your account")
|
|
264
264
|
return info
|
|
265
265
|
|
|
266
|
+
def _get_effective_new_name(
|
|
267
|
+
self, project_id: int, name: str, change_name_if_conflict: bool, parent_id: int = None
|
|
268
|
+
):
|
|
269
|
+
return (
|
|
270
|
+
self._get_free_name(
|
|
271
|
+
exist_check_fn=lambda name: self.get_info_by_name(
|
|
272
|
+
project_id, name, parent_id=parent_id
|
|
273
|
+
)
|
|
274
|
+
is not None,
|
|
275
|
+
name=name,
|
|
276
|
+
)
|
|
277
|
+
if change_name_if_conflict
|
|
278
|
+
else name
|
|
279
|
+
)
|
|
280
|
+
|
|
266
281
|
def create(
|
|
267
282
|
self,
|
|
268
283
|
project_id: int,
|
|
@@ -306,9 +321,10 @@ class DatasetApi(UpdateableModule, RemoveableModuleApi):
|
|
|
306
321
|
print(len(new_ds_info)) # 2
|
|
307
322
|
"""
|
|
308
323
|
effective_name = self._get_effective_new_name(
|
|
309
|
-
|
|
324
|
+
project_id=project_id,
|
|
310
325
|
name=name,
|
|
311
326
|
change_name_if_conflict=change_name_if_conflict,
|
|
327
|
+
parent_id=parent_id,
|
|
312
328
|
)
|
|
313
329
|
response = self._api.post(
|
|
314
330
|
"datasets.add",
|
supervisely/api/project_api.py
CHANGED
|
@@ -95,6 +95,7 @@ class ProjectInfo(NamedTuple):
|
|
|
95
95
|
settings: dict
|
|
96
96
|
import_settings: dict
|
|
97
97
|
version: dict
|
|
98
|
+
created_by_id: int
|
|
98
99
|
|
|
99
100
|
@property
|
|
100
101
|
def image_preview_url(self):
|
|
@@ -169,6 +170,7 @@ class ProjectApi(CloneableModuleApi, UpdateableModule, RemoveableModuleApi):
|
|
|
169
170
|
backup_archive={},
|
|
170
171
|
team_id=2,
|
|
171
172
|
import_settings={}
|
|
173
|
+
version={'id': 260, 'version': 3}
|
|
172
174
|
)
|
|
173
175
|
"""
|
|
174
176
|
return [
|
|
@@ -191,6 +193,7 @@ class ProjectApi(CloneableModuleApi, UpdateableModule, RemoveableModuleApi):
|
|
|
191
193
|
ApiField.SETTINGS,
|
|
192
194
|
ApiField.IMPORT_SETTINGS,
|
|
193
195
|
ApiField.VERSION,
|
|
196
|
+
ApiField.CREATED_BY_ID,
|
|
194
197
|
]
|
|
195
198
|
|
|
196
199
|
@staticmethod
|
|
@@ -427,7 +430,7 @@ class ProjectApi(CloneableModuleApi, UpdateableModule, RemoveableModuleApi):
|
|
|
427
430
|
"""
|
|
428
431
|
|
|
429
432
|
fields = [
|
|
430
|
-
x for x in self.info_sequence() if x not in (ApiField.ITEMS_COUNT, ApiField.SETTINGS)
|
|
433
|
+
x for x in self.info_sequence() if x not in (ApiField.ITEMS_COUNT, ApiField.SETTINGS, ApiField.CREATED_BY_ID)
|
|
431
434
|
]
|
|
432
435
|
|
|
433
436
|
info = super().get_info_by_name(parent_id, name, fields)
|
|
@@ -128,7 +128,9 @@ class VolumeAnnotationAPI(EntityAnnotationAPI):
|
|
|
128
128
|
volume_info = self._api.volume.get_info_by_id(volume_id)
|
|
129
129
|
return self._download(volume_info.dataset_id, volume_id)
|
|
130
130
|
|
|
131
|
-
def append(
|
|
131
|
+
def append(
|
|
132
|
+
self, volume_id: int, ann: VolumeAnnotation, key_id_map: KeyIdMap = None, volume_info=None
|
|
133
|
+
):
|
|
132
134
|
"""
|
|
133
135
|
Loads VolumeAnnotation to a given volume ID in the API.
|
|
134
136
|
|
|
@@ -159,13 +161,14 @@ class VolumeAnnotationAPI(EntityAnnotationAPI):
|
|
|
159
161
|
else:
|
|
160
162
|
figures = ann.figures
|
|
161
163
|
|
|
162
|
-
|
|
164
|
+
if volume_info is None:
|
|
165
|
+
volume_info = self._api.volume.get_info_by_id(volume_id)
|
|
163
166
|
self._append(
|
|
164
167
|
self._api.volume.tag,
|
|
165
168
|
self._api.volume.object,
|
|
166
169
|
self._api.volume.figure,
|
|
167
|
-
|
|
168
|
-
|
|
170
|
+
volume_info.project_id,
|
|
171
|
+
volume_info.dataset_id,
|
|
169
172
|
volume_id,
|
|
170
173
|
ann.tags,
|
|
171
174
|
ann.objects,
|
|
@@ -73,20 +73,28 @@ class ExperimentSelector(Widget):
|
|
|
73
73
|
|
|
74
74
|
# col 3 project
|
|
75
75
|
self._training_project_id = experiment_info.project_id
|
|
76
|
-
self.
|
|
77
|
-
self.
|
|
78
|
-
|
|
76
|
+
if self._training_project_id is None:
|
|
77
|
+
self._training_project_info = None
|
|
78
|
+
else:
|
|
79
|
+
self._training_project_info = self._api.project.get_info_by_id(
|
|
80
|
+
self._training_project_id
|
|
81
|
+
)
|
|
79
82
|
|
|
80
83
|
# col 4 checkpoints
|
|
81
84
|
self._checkpoints = experiment_info.checkpoints
|
|
82
85
|
|
|
83
86
|
self._checkpoints_names = []
|
|
84
87
|
self._checkpoints_paths = []
|
|
88
|
+
self._best_checkpoint_value = None
|
|
85
89
|
for checkpoint_path in self._checkpoints:
|
|
86
90
|
self._checkpoints_names.append(get_file_name_with_ext(checkpoint_path))
|
|
87
91
|
self._checkpoints_paths.append(
|
|
88
92
|
os.path.join(experiment_info.artifacts_dir, checkpoint_path)
|
|
89
93
|
)
|
|
94
|
+
if experiment_info.best_checkpoint == get_file_name_with_ext(checkpoint_path):
|
|
95
|
+
self._best_checkpoint = os.path.join(
|
|
96
|
+
experiment_info.artifacts_dir, checkpoint_path
|
|
97
|
+
)
|
|
90
98
|
|
|
91
99
|
# col 5 session
|
|
92
100
|
self._session_link = self._generate_session_link()
|
|
@@ -234,6 +242,8 @@ class ExperimentSelector(Widget):
|
|
|
234
242
|
for path, name in zip(self._checkpoints_paths, self._checkpoints_names):
|
|
235
243
|
checkpoint_selector_items.append(Select.Item(value=path, label=name))
|
|
236
244
|
checkpoint_selector = Select(items=checkpoint_selector_items)
|
|
245
|
+
if self._best_checkpoint_value is not None:
|
|
246
|
+
checkpoint_selector.set_value(self._best_checkpoint)
|
|
237
247
|
return checkpoint_selector
|
|
238
248
|
|
|
239
249
|
def _create_session_widget(self) -> Text:
|
|
@@ -3,6 +3,7 @@ import string
|
|
|
3
3
|
from abc import abstractmethod
|
|
4
4
|
from collections import defaultdict
|
|
5
5
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
6
|
+
from datetime import datetime
|
|
6
7
|
from json import JSONDecodeError
|
|
7
8
|
from os.path import dirname, join
|
|
8
9
|
from time import time
|
|
@@ -14,8 +15,9 @@ from supervisely import logger
|
|
|
14
15
|
from supervisely._utils import abs_url, is_development
|
|
15
16
|
from supervisely.api.api import Api, ApiField
|
|
16
17
|
from supervisely.api.file_api import FileInfo
|
|
17
|
-
from supervisely.io.fs import silent_remove
|
|
18
|
+
from supervisely.io.fs import get_file_name_with_ext, silent_remove
|
|
18
19
|
from supervisely.io.json import dump_json_file
|
|
20
|
+
from supervisely.nn.experiments import ExperimentInfo
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
class TrainInfo(NamedTuple):
|
|
@@ -53,6 +55,7 @@ class BaseTrainArtifacts:
|
|
|
53
55
|
self._metadata_file_name: str = "train_info.json"
|
|
54
56
|
|
|
55
57
|
self._app_name: str = None
|
|
58
|
+
self._framework_name: str = None
|
|
56
59
|
self._framework_folder: str = None
|
|
57
60
|
self._weights_folder: str = None
|
|
58
61
|
self._task_type: str = None
|
|
@@ -91,6 +94,16 @@ class BaseTrainArtifacts:
|
|
|
91
94
|
"""
|
|
92
95
|
return self._app_name
|
|
93
96
|
|
|
97
|
+
@property
|
|
98
|
+
def framework_name(self):
|
|
99
|
+
"""
|
|
100
|
+
Framework name.
|
|
101
|
+
|
|
102
|
+
:return: The framework name.
|
|
103
|
+
:rtype: str
|
|
104
|
+
"""
|
|
105
|
+
return self._framework_name
|
|
106
|
+
|
|
94
107
|
@property
|
|
95
108
|
def framework_folder(self):
|
|
96
109
|
"""
|
|
@@ -518,6 +531,84 @@ class BaseTrainArtifacts:
|
|
|
518
531
|
logger.debug(f"Listing time: '{format(end_time - start_time, '.6f')}' sec")
|
|
519
532
|
return train_infos
|
|
520
533
|
|
|
534
|
+
def get_list_experiment_info(self, sort: Literal["desc", "asc"] = "desc") -> List[TrainInfo]:
|
|
535
|
+
def build_experiment_info_from_train_info(
|
|
536
|
+
api: Api, train_info: TrainInfo
|
|
537
|
+
) -> ExperimentInfo:
|
|
538
|
+
|
|
539
|
+
checkpoints = []
|
|
540
|
+
for chk in train_info.checkpoints:
|
|
541
|
+
if self.weights_folder:
|
|
542
|
+
checkpoints.append(join(self.weights_folder, chk.name))
|
|
543
|
+
else:
|
|
544
|
+
checkpoints.append(chk.name)
|
|
545
|
+
|
|
546
|
+
best_checkpoint = next(
|
|
547
|
+
(chk.name for chk in train_info.checkpoints if "best" in chk.name), None
|
|
548
|
+
)
|
|
549
|
+
if not best_checkpoint and checkpoints:
|
|
550
|
+
best_checkpoint = get_file_name_with_ext(checkpoints[-1])
|
|
551
|
+
|
|
552
|
+
task_info = api.task.get_info_by_id(train_info.task_id)
|
|
553
|
+
workspace_id = task_info["workspaceId"]
|
|
554
|
+
|
|
555
|
+
project = api.project.get_info_by_name(workspace_id, train_info.project_name)
|
|
556
|
+
project_id = project.id if project else None
|
|
557
|
+
|
|
558
|
+
model_files = {}
|
|
559
|
+
if train_info.config_path:
|
|
560
|
+
model_files["config"] = self.get_config_path(train_info.artifacts_folder).replace(
|
|
561
|
+
train_info.artifacts_folder, ""
|
|
562
|
+
)
|
|
563
|
+
|
|
564
|
+
input_datetime = task_info["startedAt"]
|
|
565
|
+
parsed_datetime = datetime.strptime(input_datetime, "%Y-%m-%dT%H:%M:%S.%fZ")
|
|
566
|
+
date_time = parsed_datetime.strftime("%Y-%m-%d %H:%M:%S")
|
|
567
|
+
|
|
568
|
+
experiment_info_data = {
|
|
569
|
+
"experiment_name": f"Unknown {self.framework_name} experiment",
|
|
570
|
+
"framework_name": self.framework_name,
|
|
571
|
+
"model_name": f"Unknown {self.framework_name} model",
|
|
572
|
+
"task_type": train_info.task_type,
|
|
573
|
+
"project_id": project_id,
|
|
574
|
+
"task_id": train_info.task_id,
|
|
575
|
+
"model_files": model_files,
|
|
576
|
+
"checkpoints": checkpoints,
|
|
577
|
+
"best_checkpoint": best_checkpoint,
|
|
578
|
+
"artifacts_dir": train_info.artifacts_folder,
|
|
579
|
+
"datetime": date_time,
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
experiment_info_fields = {
|
|
583
|
+
field.name
|
|
584
|
+
for field in ExperimentInfo.__dataclass_fields__.values() # pylint: disable=no-member
|
|
585
|
+
}
|
|
586
|
+
for field in experiment_info_fields:
|
|
587
|
+
if field not in experiment_info_data:
|
|
588
|
+
experiment_info_data[field] = None
|
|
589
|
+
|
|
590
|
+
return ExperimentInfo(**experiment_info_data)
|
|
591
|
+
|
|
592
|
+
train_infos = self.get_list(sort)
|
|
593
|
+
|
|
594
|
+
# Sync version
|
|
595
|
+
# Uncomment for debug
|
|
596
|
+
# experiment_infos = [
|
|
597
|
+
# convert_traininfo_to_experimentinfo(api, framework_cls, train_info)
|
|
598
|
+
# for train_info in train_infos
|
|
599
|
+
# ]
|
|
600
|
+
# return experiment_infos
|
|
601
|
+
|
|
602
|
+
# Async version
|
|
603
|
+
with ThreadPoolExecutor() as executor:
|
|
604
|
+
experiment_infos = list(
|
|
605
|
+
executor.map(
|
|
606
|
+
lambda t: build_experiment_info_from_train_info(self._api, t),
|
|
607
|
+
train_infos,
|
|
608
|
+
)
|
|
609
|
+
)
|
|
610
|
+
return [info for info in experiment_infos if info is not None]
|
|
611
|
+
|
|
521
612
|
def get_available_task_types(self) -> List[str]:
|
|
522
613
|
"""
|
|
523
614
|
Get available task types.
|
|
@@ -10,6 +10,7 @@ class Detectron2(BaseTrainArtifacts):
|
|
|
10
10
|
super().__init__(team_id)
|
|
11
11
|
|
|
12
12
|
self._app_name = "Train Detectron2"
|
|
13
|
+
self._framework_name = "Detectron2"
|
|
13
14
|
self._framework_folder = "/detectron2"
|
|
14
15
|
self._weights_folder = "checkpoints"
|
|
15
16
|
self._legacy_weights_folder = "detectron_data"
|
|
@@ -10,6 +10,7 @@ class MMClassification(BaseTrainArtifacts):
|
|
|
10
10
|
super().__init__(team_id)
|
|
11
11
|
|
|
12
12
|
self._app_name = "Train MMClassification"
|
|
13
|
+
self._framework_name = "MMClassification"
|
|
13
14
|
self._framework_folder = "/mmclassification"
|
|
14
15
|
self._weights_folder = "checkpoints"
|
|
15
16
|
self._task_type = "classification"
|
|
@@ -13,6 +13,7 @@ class MMDetection(BaseTrainArtifacts):
|
|
|
13
13
|
super().__init__(team_id)
|
|
14
14
|
|
|
15
15
|
self._app_name = "Train MMDetection"
|
|
16
|
+
self._framework_name = "MMDetection"
|
|
16
17
|
self._framework_folder = "/mmdetection"
|
|
17
18
|
self._weights_folder = "checkpoints/data"
|
|
18
19
|
self._task_type = None
|
|
@@ -58,6 +59,7 @@ class MMDetection3(BaseTrainArtifacts):
|
|
|
58
59
|
super().__init__(team_id)
|
|
59
60
|
|
|
60
61
|
self._app_name = "Train MMDetection 3.0"
|
|
62
|
+
self._framework_name = "MMDetection 3.0"
|
|
61
63
|
self._framework_folder = "/mmdetection-3"
|
|
62
64
|
self._weights_folder = None
|
|
63
65
|
self._task_type = None
|
|
@@ -10,6 +10,7 @@ class MMSegmentation(BaseTrainArtifacts):
|
|
|
10
10
|
super().__init__(team_id)
|
|
11
11
|
|
|
12
12
|
self._app_name = "Train MMSegmentation"
|
|
13
|
+
self._framework_name = "MMSegmentation"
|
|
13
14
|
self._framework_folder = "/mmsegmentation"
|
|
14
15
|
self._weights_folder = "checkpoints/data"
|
|
15
16
|
self._task_type = "instance segmentation"
|
supervisely/nn/artifacts/ritm.py
CHANGED
supervisely/nn/artifacts/unet.py
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from supervisely.nn.artifacts.artifacts import BaseTrainArtifacts
|
|
2
|
+
from supervisely.nn.artifacts import (
|
|
3
|
+
YOLOv5,
|
|
4
|
+
YOLOv5v2,
|
|
5
|
+
YOLOv8,
|
|
6
|
+
MMClassification,
|
|
7
|
+
MMSegmentation,
|
|
8
|
+
MMDetection,
|
|
9
|
+
MMDetection3,
|
|
10
|
+
Detectron2,
|
|
11
|
+
UNet,
|
|
12
|
+
RITM,
|
|
13
|
+
RTDETR,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class FrameworkName:
|
|
18
|
+
YOLOV5 = "YOLOv5"
|
|
19
|
+
YOLOV5V2 = "YOLOv5 2.0"
|
|
20
|
+
YOLOV8 = "YOLOv8+"
|
|
21
|
+
MMCLASSIFICATION = "MMClassification"
|
|
22
|
+
MMSEGMENTATION = "MMSegmentation"
|
|
23
|
+
MMDETECTION = "MMDetection"
|
|
24
|
+
MMDETECTION3 = "MMDetection 3.0"
|
|
25
|
+
RTDETR = "RT-DETR"
|
|
26
|
+
DETECTRON2 = "Detectron2"
|
|
27
|
+
UNET = "UNet"
|
|
28
|
+
RITM = "RITM"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class FrameworkMapper:
|
|
32
|
+
_map = {
|
|
33
|
+
FrameworkName.YOLOV5: YOLOv5,
|
|
34
|
+
FrameworkName.YOLOV5V2: YOLOv5v2,
|
|
35
|
+
FrameworkName.YOLOV8: YOLOv8,
|
|
36
|
+
FrameworkName.MMCLASSIFICATION: MMClassification,
|
|
37
|
+
FrameworkName.MMSEGMENTATION: MMSegmentation,
|
|
38
|
+
FrameworkName.MMDETECTION: MMDetection,
|
|
39
|
+
FrameworkName.MMDETECTION3: MMDetection3,
|
|
40
|
+
FrameworkName.RTDETR: RTDETR,
|
|
41
|
+
FrameworkName.DETECTRON2: Detectron2,
|
|
42
|
+
FrameworkName.UNET: UNet,
|
|
43
|
+
FrameworkName.RITM: RITM,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def get_framework_cls(cls, name: str, team_id: int) -> BaseTrainArtifacts:
|
|
48
|
+
if name not in cls._map:
|
|
49
|
+
raise ValueError(f"Unknown framework: {name}")
|
|
50
|
+
return cls._map[name](team_id)
|
|
@@ -10,6 +10,7 @@ class YOLOv5(BaseTrainArtifacts):
|
|
|
10
10
|
super().__init__(team_id)
|
|
11
11
|
|
|
12
12
|
self._app_name = "Train YOLOv5"
|
|
13
|
+
self._framework_name = "YOLOv5"
|
|
13
14
|
self._framework_folder = "/yolov5_train"
|
|
14
15
|
self._weights_folder = "weights"
|
|
15
16
|
self._task_type = "object detection"
|
|
@@ -39,6 +40,7 @@ class YOLOv5v2(YOLOv5):
|
|
|
39
40
|
super().__init__(team_id)
|
|
40
41
|
|
|
41
42
|
self._app_name = "Train YOLOv5 2.0"
|
|
43
|
+
self._framework_name = "YOLOv5 2.0"
|
|
42
44
|
self._framework_folder = "/yolov5_2.0_train"
|
|
43
45
|
self._weights_folder = "weights"
|
|
44
46
|
self._task_type = "object detection"
|
supervisely/nn/experiments.py
CHANGED
|
@@ -2,13 +2,12 @@ from concurrent.futures import ThreadPoolExecutor
|
|
|
2
2
|
from dataclasses import dataclass, fields
|
|
3
3
|
from json import JSONDecodeError
|
|
4
4
|
from os.path import dirname, join
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import List
|
|
6
6
|
|
|
7
7
|
import requests
|
|
8
8
|
|
|
9
9
|
from supervisely import logger
|
|
10
10
|
from supervisely.api.api import Api, ApiField
|
|
11
|
-
from supervisely.api.file_api import FileInfo
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
@dataclass
|
|
@@ -51,7 +50,9 @@ class ExperimentInfo:
|
|
|
51
50
|
"""Evaluation metrics"""
|
|
52
51
|
|
|
53
52
|
|
|
54
|
-
def get_experiment_infos(
|
|
53
|
+
def get_experiment_infos(
|
|
54
|
+
api: Api, team_id: int, framework_name: str
|
|
55
|
+
) -> List[ExperimentInfo]:
|
|
55
56
|
"""
|
|
56
57
|
Get experiments from the specified framework folder for Train v2
|
|
57
58
|
|
|
@@ -78,7 +79,9 @@ def get_experiment_infos(api: Api, team_id: int, framework_name: str) -> List[Ex
|
|
|
78
79
|
experiments_folder = "/experiments"
|
|
79
80
|
experiment_infos = []
|
|
80
81
|
|
|
81
|
-
file_infos = api.file.list(
|
|
82
|
+
file_infos = api.file.list(
|
|
83
|
+
team_id, experiments_folder, recursive=True, return_type="fileinfo"
|
|
84
|
+
)
|
|
82
85
|
sorted_experiment_paths = []
|
|
83
86
|
for file_info in file_infos:
|
|
84
87
|
if not file_info.path.endswith(metadata_name):
|
|
@@ -101,7 +104,9 @@ def get_experiment_infos(api: Api, team_id: int, framework_name: str) -> List[Ex
|
|
|
101
104
|
required_fields = {field.name for field in fields(ExperimentInfo)}
|
|
102
105
|
missing_fields = required_fields - response_json.keys()
|
|
103
106
|
if missing_fields:
|
|
104
|
-
logger.debug(
|
|
107
|
+
logger.debug(
|
|
108
|
+
f"Missing fields: {missing_fields} for '{experiment_path}'"
|
|
109
|
+
)
|
|
105
110
|
return None
|
|
106
111
|
return ExperimentInfo(**response_json)
|
|
107
112
|
except requests.exceptions.RequestException as e:
|
|
@@ -112,9 +117,10 @@ def get_experiment_infos(api: Api, team_id: int, framework_name: str) -> List[Ex
|
|
|
112
117
|
logger.error(f"TypeError for '{experiment_path}': {e}")
|
|
113
118
|
return None
|
|
114
119
|
|
|
115
|
-
# Error
|
|
116
120
|
with ThreadPoolExecutor() as executor:
|
|
117
|
-
experiment_infos = list(
|
|
121
|
+
experiment_infos = list(
|
|
122
|
+
executor.map(fetch_experiment_data, sorted_experiment_paths)
|
|
123
|
+
)
|
|
118
124
|
|
|
119
125
|
experiment_infos = [info for info in experiment_infos if info is not None]
|
|
120
126
|
return experiment_infos
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Literal
|
|
2
2
|
|
|
3
3
|
import supervisely.io.env as sly_env
|
|
4
|
+
from supervisely import logger
|
|
4
5
|
from supervisely.api.api import Api
|
|
5
6
|
from supervisely.app.widgets import (
|
|
6
7
|
Button,
|
|
@@ -13,6 +14,7 @@ from supervisely.app.widgets import (
|
|
|
13
14
|
)
|
|
14
15
|
from supervisely.nn.experiments import get_experiment_infos
|
|
15
16
|
from supervisely.nn.utils import ModelSource
|
|
17
|
+
from supervisely.nn.artifacts.utils import FrameworkMapper, FrameworkName
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
class ModelSelector:
|
|
@@ -22,12 +24,21 @@ class ModelSelector:
|
|
|
22
24
|
|
|
23
25
|
def __init__(self, api: Api, framework: str, models: list, app_options: dict = {}):
|
|
24
26
|
self.display_widgets = []
|
|
25
|
-
self.team_id = sly_env.team_id()
|
|
27
|
+
self.team_id = sly_env.team_id()
|
|
26
28
|
self.models = models
|
|
27
29
|
|
|
28
30
|
# GUI Components
|
|
29
31
|
self.pretrained_models_table = PretrainedModelsSelector(self.models)
|
|
32
|
+
|
|
30
33
|
experiment_infos = get_experiment_infos(api, self.team_id, framework)
|
|
34
|
+
if app_options.get("legacy_checkpoints", False):
|
|
35
|
+
try:
|
|
36
|
+
framework_cls = FrameworkMapper.get_framework_cls(framework, self.team_id)
|
|
37
|
+
legacy_experiment_infos = framework_cls.get_list_experiment_info()
|
|
38
|
+
experiment_infos = experiment_infos + legacy_experiment_infos
|
|
39
|
+
except:
|
|
40
|
+
logger.warn(f"Legacy checkpoints are not available for '{framework}'")
|
|
41
|
+
|
|
31
42
|
self.experiment_selector = ExperimentSelector(self.team_id, experiment_infos)
|
|
32
43
|
self.model_source_tabs = RadioTabs(
|
|
33
44
|
titles=[ModelSource.PRETRAINED, ModelSource.CUSTOM],
|
|
@@ -24,7 +24,7 @@ supervisely/api/agent_api.py,sha256=ShWAIlXcWXcyI9fqVuP5GZVCigCMJmjnvdGUfLspD6Y,
|
|
|
24
24
|
supervisely/api/annotation_api.py,sha256=kB9l0NhQEkunGDC9fWjNzf5DdhqRF1tv-RRnIbkV2k0,64941
|
|
25
25
|
supervisely/api/api.py,sha256=A4EY7MtLWw4a29Wd63SjQs2CkS3KAiYkVLyuuZn1LdM,65371
|
|
26
26
|
supervisely/api/app_api.py,sha256=-T4sISQ7POyR2yirf1kEWj4JaJFpJxCyRWqbf_99Jak,67036
|
|
27
|
-
supervisely/api/dataset_api.py,sha256=
|
|
27
|
+
supervisely/api/dataset_api.py,sha256=eovT6l62jgjlRyCZ6IvoudUBfDxv9Hjj3Ap8IuCLd7I,41290
|
|
28
28
|
supervisely/api/file_api.py,sha256=c4iIzH2BF8-GLFLk_wc9Qz225AbHhbzH22wv5HdsGg4,83128
|
|
29
29
|
supervisely/api/github_api.py,sha256=NIexNjEer9H5rf5sw2LEZd7C1WR-tK4t6IZzsgeAAwQ,623
|
|
30
30
|
supervisely/api/image_annotation_tool_api.py,sha256=YcUo78jRDBJYvIjrd-Y6FJAasLta54nnxhyaGyanovA,5237
|
|
@@ -36,7 +36,7 @@ supervisely/api/module_api.py,sha256=ajVPU5bH1sB-l2PwWq_xtFxSmZIBikflousOxiAYmW4
|
|
|
36
36
|
supervisely/api/neural_network_api.py,sha256=ktPVRO4Jeulougio8F0mioJJHwRJcX250Djp1wBoQ9c,7620
|
|
37
37
|
supervisely/api/object_class_api.py,sha256=-rQcKwhBw3iL9KNH9c1ROgoimgWM1ls6Wi_tb1R-MzY,7683
|
|
38
38
|
supervisely/api/plugin_api.py,sha256=TlfrosdRuYG4NUxk92QiQoVaOdztFspPpygyVa3M3zk,5283
|
|
39
|
-
supervisely/api/project_api.py,sha256=
|
|
39
|
+
supervisely/api/project_api.py,sha256=ZTRx7LXsPLjMuGq_PhugPgN-OsGMtTRxputH9EA9iZ0,78774
|
|
40
40
|
supervisely/api/project_class_api.py,sha256=5cyjdGPPb2tpttu5WmYoOxUNiDxqiojschkhZumF0KM,1426
|
|
41
41
|
supervisely/api/remote_storage_api.py,sha256=xy9-j5hSftVcAILyqF_mQdQ1DUywt9msq2QYuSE-PVY,15032
|
|
42
42
|
supervisely/api/report_api.py,sha256=Om7CGulUbQ4BuJ16eDtz7luLe0JQNqab-LoLpUXu7YE,7123
|
|
@@ -70,7 +70,7 @@ supervisely/api/video/video_frame_api.py,sha256=4GwSI4xdCNYEUvTqzKc-Ewd44fw5zqkF
|
|
|
70
70
|
supervisely/api/video/video_object_api.py,sha256=IC0NP8EoIT_d3xxDRgz2cA3ixSiuJ5ymy64eS-RfmDM,2227
|
|
71
71
|
supervisely/api/video/video_tag_api.py,sha256=oJgdJt_0w-5UfXaxZ7jdxK0PetZjax1vOfjm0IMYwe8,12266
|
|
72
72
|
supervisely/api/volume/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
|
-
supervisely/api/volume/volume_annotation_api.py,sha256=
|
|
73
|
+
supervisely/api/volume/volume_annotation_api.py,sha256=dPtZSXIz-5us1roG8d4WMt8VU67DWhD6lbBmZv49hy8,18279
|
|
74
74
|
supervisely/api/volume/volume_api.py,sha256=-n3r5qj4I4EtoERKTHFT8PpsKFJ141SvQfamIcHqWK4,55387
|
|
75
75
|
supervisely/api/volume/volume_figure_api.py,sha256=WwmcMw7o3Nvyv52tzmz64yF-WJI0qzAU-zL2JlD7_w0,26039
|
|
76
76
|
supervisely/api/volume/volume_object_api.py,sha256=F7pLV2MTlBlyN6fEKdxBSUatIMGWSuu8bWj3Hvcageo,2139
|
|
@@ -247,7 +247,7 @@ supervisely/app/widgets/empty/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
|
|
|
247
247
|
supervisely/app/widgets/empty/empty.py,sha256=fCr8I7CQ2XLo59bl2txjDrblOGiu0TzUcM-Pq6s7gKY,1285
|
|
248
248
|
supervisely/app/widgets/empty/template.html,sha256=aDBKkin5aLuqByzNN517-rTYCGIg5SPKgnysYMPYjv8,40
|
|
249
249
|
supervisely/app/widgets/experiment_selector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
250
|
-
supervisely/app/widgets/experiment_selector/experiment_selector.py,sha256=
|
|
250
|
+
supervisely/app/widgets/experiment_selector/experiment_selector.py,sha256=XZxhpD3utmHsHhKxo34-wJIfOaKXXznrFQVnVaHVWik,19456
|
|
251
251
|
supervisely/app/widgets/experiment_selector/style.css,sha256=-zPPXHnJvatYj_xVVAb7T8uoSsUTyhm5xCKWkkFQ78E,548
|
|
252
252
|
supervisely/app/widgets/experiment_selector/template.html,sha256=k7f_Xl6nDUXXwu6IY_RblYni5TbZRRxCBduY5O_SyFs,2908
|
|
253
253
|
supervisely/app/widgets/fast_table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -710,22 +710,23 @@ supervisely/metric/pixel_accuracy.py,sha256=qjtxInOTkGDwPeLUnjBdzOrVRT3V6kGGOWjB
|
|
|
710
710
|
supervisely/metric/precision_recall_metric.py,sha256=4AQCkcB84mpYQS94yJ-wkG1LBuXlQf3X_tI9f67vtR8,3426
|
|
711
711
|
supervisely/metric/projects_applier.py,sha256=ORtgLQHYtNi4KYsSGaGPPWiZPexTJF9IWqX_RuLRxPk,3415
|
|
712
712
|
supervisely/nn/__init__.py,sha256=w2gZ6pCreaTYyhZV8PZrYctqmCu_7sbJ-WGegs7mouw,570
|
|
713
|
-
supervisely/nn/experiments.py,sha256=
|
|
713
|
+
supervisely/nn/experiments.py,sha256=tM0dYkaMphrw_dnSRQatBf1A-uEq1jfL8pdPF8V7g9o,4553
|
|
714
714
|
supervisely/nn/prediction_dto.py,sha256=8QQE6h_feOf3bjWtyG_PoU8FIQrr4g8PoMOyoscmqJM,1697
|
|
715
715
|
supervisely/nn/task_type.py,sha256=UJvSJ4L3I08j_e6sU6Ptu7kS5p1H09rfhfoDUSZ2iys,522
|
|
716
716
|
supervisely/nn/utils.py,sha256=-Xjv5KLu8CTtyi7acqsIX1E0dDwKZPED4D6b4Z_Ln3k,1451
|
|
717
717
|
supervisely/nn/artifacts/__init__.py,sha256=m7KYTMzEJnoV9wcU_0xzgLuPz69Dqp9va0fP32tohV4,576
|
|
718
|
-
supervisely/nn/artifacts/artifacts.py,sha256=
|
|
719
|
-
supervisely/nn/artifacts/detectron2.py,sha256=
|
|
718
|
+
supervisely/nn/artifacts/artifacts.py,sha256=SWVwaE40SPNElLp2NsRSOVh_ESRIXXZ1I-tMLEUYmTQ,20751
|
|
719
|
+
supervisely/nn/artifacts/detectron2.py,sha256=6iu5Yslc-SxCKJVNl6sn84qeXmD-JIQShJIxuLdzf2o,1673
|
|
720
720
|
supervisely/nn/artifacts/hrda.py,sha256=3DzbjDIt9YuLozMrKmYYw13oxc14xju2vzbxKVq2G4I,1073
|
|
721
|
-
supervisely/nn/artifacts/mmclassification.py,sha256=
|
|
722
|
-
supervisely/nn/artifacts/mmdetection.py,sha256=
|
|
723
|
-
supervisely/nn/artifacts/mmsegmentation.py,sha256=
|
|
724
|
-
supervisely/nn/artifacts/ritm.py,sha256=
|
|
725
|
-
supervisely/nn/artifacts/rtdetr.py,sha256=
|
|
726
|
-
supervisely/nn/artifacts/unet.py,sha256=
|
|
727
|
-
supervisely/nn/artifacts/
|
|
728
|
-
supervisely/nn/artifacts/
|
|
721
|
+
supervisely/nn/artifacts/mmclassification.py,sha256=M0m9HHF5koHsl5RuFkRU0_clckA1sFty3X6awB2eKNo,1527
|
|
722
|
+
supervisely/nn/artifacts/mmdetection.py,sha256=RxrCPODJzJqu9rtNtkndiGiHiPnusIRQWmwbAzZ9PGU,4812
|
|
723
|
+
supervisely/nn/artifacts/mmsegmentation.py,sha256=VTh0hKgaDeF1SHWWxTTXgt7h_mpLuXER1_2Jeb3ytHI,1331
|
|
724
|
+
supervisely/nn/artifacts/ritm.py,sha256=lff_lx8IqmhvE9qF8rtbddGkjgVF-abKCtQEi_kLhkk,1969
|
|
725
|
+
supervisely/nn/artifacts/rtdetr.py,sha256=aKNieooBl8VX5BDwaNkr9vj142rquKQU4xPDB31m_Fw,1229
|
|
726
|
+
supervisely/nn/artifacts/unet.py,sha256=ifipjAWLANZoZ5Er5qxCykBIV-Zu_NQKtenjFdgpbic,1586
|
|
727
|
+
supervisely/nn/artifacts/utils.py,sha256=C4EaMi95MAwtK5TOnhK4sQ1BWvgwYBxXyRStkhYrYv8,1356
|
|
728
|
+
supervisely/nn/artifacts/yolov5.py,sha256=slh05EpQsxqgKwB9KMClshdBxPBN3ZWZ6S4B80ECEt4,1724
|
|
729
|
+
supervisely/nn/artifacts/yolov8.py,sha256=sFd9kU7Gdowq6WH1S3NdlQeoL9jjQKmRYb51fG_wbDk,1446
|
|
729
730
|
supervisely/nn/benchmark/__init__.py,sha256=7jDezvavJFtO9mDeB2TqW8N4sD8TsHQBPpA9RESleIQ,610
|
|
730
731
|
supervisely/nn/benchmark/base_benchmark.py,sha256=yb0zaMjQIQ5A0hcukf1MVuIh877ie2yUVJLmaHCXI90,25451
|
|
731
732
|
supervisely/nn/benchmark/base_evaluator.py,sha256=MqLw42bXxGLKbI8pKMoCe8qmTouQ38zoBpxO3jAtEtM,4355
|
|
@@ -946,7 +947,7 @@ supervisely/nn/training/gui/classes_selector.py,sha256=8UgzA4aogOAr1s42smwEcDbga
|
|
|
946
947
|
supervisely/nn/training/gui/gui.py,sha256=Xco1yXcfVSPnbBwZDYGIOysyN7WRxIV_r6G1vtCgkpE,22591
|
|
947
948
|
supervisely/nn/training/gui/hyperparameters_selector.py,sha256=2qryuBss0bLcZJV8PNJ6_hKZM5Dbj2FIxTb3EULHQrE,6670
|
|
948
949
|
supervisely/nn/training/gui/input_selector.py,sha256=Jp9PnVVADv1fhndPuZdMlKuzWTOBQZogrOks5dwATlc,2179
|
|
949
|
-
supervisely/nn/training/gui/model_selector.py,sha256=
|
|
950
|
+
supervisely/nn/training/gui/model_selector.py,sha256=QTFHMf-8-rREYPk64QKoRvE4zKPC8V6tcP4H4N6nyt0,4082
|
|
950
951
|
supervisely/nn/training/gui/train_val_splits_selector.py,sha256=MLryFD2Tj_RobkFzZOeQXzXpch0eGiVFisq3FGA3dFg,8549
|
|
951
952
|
supervisely/nn/training/gui/training_logs.py,sha256=1CBqnL0l5kiZVaegJ-NLgOVI1T4EDB_rLAtumuw18Jo,3222
|
|
952
953
|
supervisely/nn/training/gui/training_process.py,sha256=yaAUHL6A9GVeiGFTd9DSTHMAQNxnlUa7oZ-j0xmLfEE,3881
|
|
@@ -1041,9 +1042,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
1041
1042
|
supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
|
|
1042
1043
|
supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
|
|
1043
1044
|
supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
|
|
1044
|
-
supervisely-6.73.
|
|
1045
|
-
supervisely-6.73.
|
|
1046
|
-
supervisely-6.73.
|
|
1047
|
-
supervisely-6.73.
|
|
1048
|
-
supervisely-6.73.
|
|
1049
|
-
supervisely-6.73.
|
|
1045
|
+
supervisely-6.73.253.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
1046
|
+
supervisely-6.73.253.dist-info/METADATA,sha256=kp6hHxnNB6C3Z7dktlJdus0Mxv_xr9xdbLBEIbsMDRM,33573
|
|
1047
|
+
supervisely-6.73.253.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
1048
|
+
supervisely-6.73.253.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
|
|
1049
|
+
supervisely-6.73.253.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
|
|
1050
|
+
supervisely-6.73.253.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|