supervisely 6.73.372__py3-none-any.whl → 6.73.374__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/_utils.py CHANGED
@@ -575,3 +575,14 @@ def removesuffix(string, suffix):
575
575
  if string.endswith(suffix):
576
576
  return string[: -len(suffix)]
577
577
  return string
578
+
579
+
580
+ def remove_non_printable(text: str) -> str:
581
+ """Remove non-printable characters from a string.
582
+
583
+ :param text: Input string
584
+ :type text: str
585
+ :return: String with non-printable characters removed
586
+ :rtype: str
587
+ """
588
+ return "".join(char for char in text if char.isprintable()).strip()
@@ -340,6 +340,7 @@ class LabelingJobApi(RemoveableBulkModuleApi, ModuleWithStatus):
340
340
  disable_confirm: Optional[bool] = None,
341
341
  disable_submit: Optional[bool] = None,
342
342
  toolbox_settings: Optional[Dict] = None,
343
+ enable_quality_check: Optional[bool] = None,
343
344
  ) -> List[LabelingJobInfo]:
344
345
  """
345
346
  Creates Labeling Job and assigns given Users to it.
@@ -382,6 +383,8 @@ class LabelingJobApi(RemoveableBulkModuleApi, ModuleWithStatus):
382
383
  :type disable_submit: bool, optional
383
384
  :param toolbox_settings: Settings for the labeling tool. Only video projects are supported.
384
385
  :type toolbox_settings: Dict, optional
386
+ :param enable_quality_check: If True, adds an intermediate step between "review" and completing the Labeling Job.
387
+ :type enable_quality_check: bool, optional
385
388
  :return: List of information about new Labeling Job. See :class:`info_sequence<info_sequence>`
386
389
  :rtype: :class:`List[LabelingJobInfo]`
387
390
  :Usage example:
@@ -499,6 +502,8 @@ class LabelingJobApi(RemoveableBulkModuleApi, ModuleWithStatus):
499
502
  meta.update({"disableConfirm": disable_confirm})
500
503
  if disable_submit is not None:
501
504
  meta.update({"disableSubmit": disable_submit})
505
+ if enable_quality_check is not None:
506
+ meta.update({"enableIntermediateReview": enable_quality_check})
502
507
 
503
508
  data = {
504
509
  ApiField.NAME: name,
@@ -198,6 +198,8 @@ class LabelingQueueApi(RemoveableBulkModuleApi, ModuleWithStatus):
198
198
  hide_figure_author: Optional[bool] = False,
199
199
  allow_review_own_annotations: Optional[bool] = False,
200
200
  skip_complete_job_on_empty: Optional[bool] = False,
201
+ enable_quality_check: Optional[bool] = None,
202
+ quality_check_user_ids: Optional[List[int]] = None,
201
203
  ) -> int:
202
204
  """
203
205
  Creates Labeling Queue and assigns given Users to it.
@@ -210,6 +212,8 @@ class LabelingQueueApi(RemoveableBulkModuleApi, ModuleWithStatus):
210
212
  :type collection_id: int, optional
211
213
  :param user_ids: User IDs in Supervisely to assign Users as labelers to Labeling Queue.
212
214
  :type user_ids: List[int]
215
+ :param reviewer_ids: User IDs in Supervisely to assign Users as reviewers to Labeling Queue.
216
+ :type reviewer_ids: List[int]
213
217
  :param readme: Additional information about Labeling Queue.
214
218
  :type readme: str, optional
215
219
  :param description: Description of Labeling Queue.
@@ -242,6 +246,16 @@ class LabelingQueueApi(RemoveableBulkModuleApi, ModuleWithStatus):
242
246
  :type disable_submit: bool, optional
243
247
  :param toolbox_settings: Settings for the labeling tool. Only video projects are supported.
244
248
  :type toolbox_settings: Dict, optional
249
+ :param hide_figure_author: If True, hides the author of the figure in the labeling tool.
250
+ :type hide_figure_author: bool, optional
251
+ :param allow_review_own_annotations: If True, allows labelers to review their own annotations.
252
+ :type allow_review_own_annotations: bool, optional
253
+ :param skip_complete_job_on_empty: If True, skips completing the Labeling Queue if there are no images to label.
254
+ :type skip_complete_job_on_empty: bool, optional
255
+ :param enable_quality_check: If True, adds an intermediate step between "review" and completing the Labeling Queue.
256
+ :type enable_quality_check: bool, optional
257
+ :param quality_check_user_ids: List of User IDs in Supervisely to assign Users as Quality Checkers to Labeling Queue.
258
+ :type quality_check_user_ids: List[int], optional
245
259
  :return: Labeling Queue ID in Supervisely.
246
260
  :rtype: int
247
261
  :Usage example:
@@ -348,6 +362,12 @@ class LabelingQueueApi(RemoveableBulkModuleApi, ModuleWithStatus):
348
362
  meta.update({"disableConfirm": disable_confirm})
349
363
  if disable_submit is not None:
350
364
  meta.update({"disableSubmit": disable_submit})
365
+ if enable_quality_check is not None:
366
+ if quality_check_user_ids is None:
367
+ raise RuntimeError(
368
+ "quality_check_user_ids must be provided if enable_quality_check is True"
369
+ )
370
+ meta.update({"enableIntermediateReview": enable_quality_check})
351
371
 
352
372
  queue_meta = {}
353
373
  if allow_review_own_annotations is True:
@@ -366,6 +386,12 @@ class LabelingQueueApi(RemoveableBulkModuleApi, ModuleWithStatus):
366
386
  data[ApiField.DATASET_ID] = dataset_id
367
387
  if collection_id is not None:
368
388
  data[ApiField.COLLECTION_ID] = collection_id
389
+ if quality_check_user_ids is not None:
390
+ if enable_quality_check is not True:
391
+ raise RuntimeError(
392
+ "quality_check_user_ids can be set only if enable_quality_check is True"
393
+ )
394
+ data[ApiField.QUALITY_CHECK_USER_IDS] = quality_check_user_ids
369
395
 
370
396
  if len(queue_meta) > 0:
371
397
  data[ApiField.QUEUE_META] = queue_meta
@@ -661,6 +661,8 @@ class ApiField:
661
661
  """"""
662
662
  COLLECTION_ID = "collectionId"
663
663
  """"""
664
+ QUALITY_CHECK_USER_IDS = "qualityCheckUserIds"
665
+ """"""
664
666
 
665
667
 
666
668
  def _get_single_item(items):
@@ -13,6 +13,7 @@ from supervisely.app.widgets_context import JinjaWidgets
13
13
  class RunAppButton(Widget):
14
14
  def __init__(
15
15
  self,
16
+ team_id: int,
16
17
  workspace_id: int,
17
18
  module_id: int,
18
19
  payload: dict = None,
@@ -26,11 +27,14 @@ class RunAppButton(Widget):
26
27
  icon_gap: Optional[int] = 5,
27
28
  available_in_offline: Optional[bool] = False,
28
29
  visible_by_vue_field: Optional[str] = "",
30
+ check_existing_task_cb: Optional[str] = "null",
29
31
  widget_id: Optional[str] = None,
30
32
  ):
31
33
  """
32
34
  Button the runs an app on Supervisely instance.
33
35
 
36
+ :param team_id: Team ID.
37
+ :type team_id: int
34
38
  :param workspace_id: Workspace ID.
35
39
  :type workspace_id: int
36
40
  :param module_id: Module ID.
@@ -53,6 +57,8 @@ class RunAppButton(Widget):
53
57
  :type available_in_offline: bool, optional
54
58
  :param visible_by_vue_field: Vue field that controls the button visibility. If set to "isStaticVersion", the button will be visible only in offline session.
55
59
  :type visible_by_vue_field: str, optional
60
+ :param check_existing_task_cb: Sets the callback function for checking existing tasks. Function should be a string (docstring) of JavaScript code.
61
+ :type check_existing_task_cb: str, optional
56
62
  :param widget_id: Widget ID.
57
63
  :type widget_id: str, optional
58
64
 
@@ -88,12 +94,13 @@ class RunAppButton(Widget):
88
94
 
89
95
  self._available_in_offline = available_in_offline
90
96
  self._visible_by_vue_field = visible_by_vue_field
91
-
92
97
  self._loading = False
93
98
  self._disabled = False
99
+ self._team_id = team_id
94
100
  self._workspace_id = workspace_id
95
101
  self._module_id = module_id
96
102
  self._payload = payload
103
+ self._check_existing_task_cb = check_existing_task_cb
97
104
 
98
105
  super().__init__(widget_id=widget_id, file_path=__file__)
99
106
 
@@ -114,6 +121,7 @@ class RunAppButton(Widget):
114
121
  - available_in_offline: If True, the button will be available in offline session.
115
122
  """
116
123
  return {
124
+ "check_existing_task_cb": self._check_existing_task_cb,
117
125
  "options": {
118
126
  "text": self._text,
119
127
  "button_type": self._button_type,
@@ -123,12 +131,13 @@ class RunAppButton(Widget):
123
131
  "disabled": self._disabled,
124
132
  "icon": self._icon,
125
133
  "available_in_offline": self._available_in_offline,
126
- }
134
+ },
127
135
  }
128
136
 
129
137
  def get_json_state(self) -> None:
130
138
  """Button widget doesn't have state, so this method returns None."""
131
139
  return {
140
+ "team_id": self._team_id,
132
141
  "workspace_id": self._workspace_id,
133
142
  "module_id": self._module_id,
134
143
  "payload": self._payload,
@@ -298,3 +307,14 @@ class RunAppButton(Widget):
298
307
  """
299
308
  self._disabled = value
300
309
  DataJson()[self.widget_id]["options"]["disabled"] = self._disabled
310
+
311
+ def set_check_existing_task_cb(self, function: str) -> None:
312
+ """Sets the callback function for checking existing tasks.
313
+ Function should be a string (docstring) of JavaScript code.
314
+
315
+ :param function: Callback function for checking existing tasks.
316
+ :type function: str
317
+ """
318
+ self._check_existing_task_cb = function
319
+ DataJson()[self.widget_id]["check_existing_task_cb"] = self._check_existing_task_cb
320
+ DataJson().send_changes()
@@ -1,46 +1,106 @@
1
- Vue.component('sly-run-app-button', {
2
- props: {
3
- 'publicApiInstance': { 'type': Object },
4
- 'workspaceId': { 'type': Number }, 'moduleId': { 'type': Number }, 'payload': { 'type': Object }, 'options': { 'type': Object }
5
- },
6
- data() {
7
- return {
8
- loading: false,
9
- };
10
- },
11
- methods: {
12
- async runApp() {
13
- try {
14
- this.loading = true;
15
-
16
- const tasks = await this.publicApiInstance.post('tasks.run.app', {
17
- params: this.payload,
18
- workspaceId: this.workspaceId,
19
- moduleId: this.moduleId,
20
- nodeId: null,
21
- }).then(response => response.data);
22
-
23
- const task = tasks[0];
24
- const origin = new URL(this.publicApiInstance.defaults.baseURL).origin;
25
- window.open(`${origin}/apps/${task.appId}/sessions/${task.taskId}`, '_blank');
26
- } finally {
27
- this.loading = false;
28
- }
29
- }
30
- },
31
- template: `
32
- <el-button
33
- :class="{'available-in-offline': options.available_in_offline}"
34
- @click="runApp"
35
- v-loading="options.loading || loading"
36
- :type="options.button_type"
37
- :plain="options.plain"
38
- :size="options.button_size"
39
- :disabled="options.disabled"
40
-
41
- >
42
- <span v-html="options.icon"></span>
43
- <span v-html="options.text"></span>
44
- </el-button>
45
- `,
1
+ Vue.component("sly-run-app-button", {
2
+ props: {
3
+ publicApiInstance: { type: Function },
4
+ workspaceId: { type: Number },
5
+ moduleId: { type: Number },
6
+ payload: { type: Object },
7
+ options: { type: Object, default: () => ({}) },
8
+ groupId: { type: Number },
9
+ checkExistingTaskCb: { type: Function, default: null },
10
+ },
11
+ data() {
12
+ return {
13
+ loading: false,
14
+ };
15
+ },
16
+ methods: {
17
+ async runApp() {
18
+ try {
19
+ this.loading = true;
20
+
21
+ if (this.checkExistingTaskCb) {
22
+ let checkExistingTaskCb =
23
+ typeof this.checkExistingTaskCb === "function"
24
+ ? this.checkExistingTaskCb
25
+ : null;
26
+
27
+ if (typeof this.checkExistingTaskCb === "string") {
28
+ console.log("checkExistingTaskCb", this.checkExistingTaskCb);
29
+ try {
30
+ checkExistingTaskCb = new Function(
31
+ "task",
32
+ this.checkExistingTaskCb
33
+ );
34
+ } catch (err) {
35
+ console.log("Error parsing checkExistingTaskCb string:", err);
36
+ }
37
+ }
38
+
39
+ console.log("Before check checkExistingTaskCb", checkExistingTaskCb);
40
+ if (checkExistingTaskCb) {
41
+ const allEntities = await this.publicApiInstance
42
+ .post("apps.list", {
43
+ withShared: true,
44
+ onlyRunning: true,
45
+ groupId: this.groupId,
46
+ filter: [
47
+ { field: "moduleId", operator: "=", value: this.moduleId },
48
+ ],
49
+ })
50
+ .then((res) => res.data?.entities || []);
51
+
52
+ const existTasks = allEntities.flatMap(
53
+ (entity) => entity.tasks || []
54
+ );
55
+
56
+ if (existTasks.length) {
57
+ const foundTask = existTasks.find((t) => checkExistingTaskCb(t));
58
+ console.log("foundTask", foundTask);
59
+
60
+ if (foundTask) {
61
+ window.open(
62
+ `/apps/${foundTask.meta.app.id}/sessions/${foundTask.id}`,
63
+ "_blank"
64
+ );
65
+ return;
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ const tasks = await this.publicApiInstance
72
+ .post("tasks.run.app", {
73
+ params: this.payload,
74
+ workspaceId: this.workspaceId,
75
+ moduleId: this.moduleId,
76
+ nodeId: null,
77
+ })
78
+ .then((response) => response.data);
79
+
80
+ const task = tasks[0];
81
+ const origin = new URL(this.publicApiInstance.defaults.baseURL).origin;
82
+ window.open(
83
+ `${origin}/apps/${task.appId}/sessions/${task.taskId}`,
84
+ "_blank"
85
+ );
86
+ } finally {
87
+ this.loading = false;
88
+ }
89
+ },
90
+ },
91
+ template: `
92
+ <el-button
93
+ :class="{'available-in-offline': options.available_in_offline}"
94
+ @click="runApp"
95
+ v-loading="options.loading || loading"
96
+ :type="options.button_type"
97
+ :plain="options.plain"
98
+ :size="options.button_size"
99
+ :disabled="options.disabled"
100
+
101
+ >
102
+ <span v-html="options.icon"></span>
103
+ <span v-html="options.text"></span>
104
+ </el-button>
105
+ `,
46
106
  });
@@ -1,10 +1,5 @@
1
- <sly-run-app-button
2
- :public-api-instance="publicApiInstance"
3
- :workspace-id="state.{{{widget.widget_id}}}.workspace_id"
4
- :module-id="state.{{{widget.widget_id}}}.module_id"
5
- :payload="state.{{{widget.widget_id}}}.payload"
6
- :options="data.{{{widget.widget_id}}}.options"
7
- {% if widget._visible_by_vue_field %}
8
- v-show="{{{widget._visible_by_vue_field}}}"
9
- {% endif %}
10
- ></sly-run-app-button>
1
+ <sly-run-app-button :public-api-instance="publicApiInstance" :group-id="state.{{{widget.widget_id}}}.team_id"
2
+ :workspace-id="state.{{{widget.widget_id}}}.workspace_id" :module-id="state.{{{widget.widget_id}}}.module_id"
3
+ :payload="state.{{{widget.widget_id}}}.payload" :options="data.{{{widget.widget_id}}}.options" {% if
4
+ widget._visible_by_vue_field %} v-show="{{{widget._visible_by_vue_field}}}" {% endif %}
5
+ :check-existing-task-cb="data.{{{widget.widget_id}}}.check_existing_task_cb"></sly-run-app-button>
@@ -36,6 +36,7 @@ class TrainingLogs:
36
36
  self.display_widgets = []
37
37
  self.app_options = app_options
38
38
  api = Api.from_env()
39
+ team_id = sly_env.team_id()
39
40
 
40
41
  # GUI Components
41
42
  self.validator_text = Text("")
@@ -73,6 +74,7 @@ class TrainingLogs:
73
74
  module_info = gui_utils.get_module_info_by_name(api, app_name)
74
75
  if module_info is not None:
75
76
  self.tensorboard_offline_button = RunAppButton(
77
+ team_id=team_id,
76
78
  workspace_id=workspace_id,
77
79
  module_id=module_info["id"],
78
80
  payload={},
@@ -81,9 +83,10 @@ class TrainingLogs:
81
83
  plain=True,
82
84
  icon="zmdi zmdi-chart",
83
85
  available_in_offline=True,
84
- visible_by_vue_field="isStaticVersion",
86
+ visible_by_vue_field=None,
85
87
  )
86
88
  self.tensorboard_offline_button.disable()
89
+ self.tensorboard_offline_button.hide()
87
90
  self.display_widgets.extend([self.tensorboard_offline_button])
88
91
  else:
89
92
  logger.warning(
@@ -136,3 +136,26 @@ def get_module_info_by_name(api: Api, app_name: str) -> Union[Dict, None]:
136
136
  if module["name"] == app_name:
137
137
  app_info = api.app.get_info(module["id"])
138
138
  return app_info
139
+
140
+
141
+ def generate_task_check_function_js(folder: str) -> str:
142
+ """
143
+ Returns JavaScript function code for checking existing tasks.
144
+
145
+ :param folder: Remote folder to check.
146
+ :type folder: str
147
+ :return: JavaScript function code for checking existing tasks.
148
+ :rtype: str
149
+ """
150
+ escaped_folder = folder.replace("'", "\\'")
151
+ js_code = f"""
152
+ if (!task || !task.meta || !task.meta.params || !task.meta.params.state) {{
153
+ return false;
154
+ }}
155
+ const taskFolder = task.meta.params.state.slyFolder;
156
+ if (!taskFolder || typeof taskFolder !== 'string') {{
157
+ return false;
158
+ }}
159
+ return taskFolder === '{escaped_folder}';
160
+ """
161
+ return js_code
@@ -10,6 +10,7 @@ import subprocess
10
10
  from datetime import datetime
11
11
  from os import getcwd, listdir, walk
12
12
  from os.path import basename, dirname, exists, expanduser, isdir, isfile, join
13
+ from time import sleep
13
14
  from typing import Any, Dict, List, Literal, Optional, Union
14
15
  from urllib.request import urlopen
15
16
 
@@ -57,6 +58,7 @@ from supervisely.nn.inference import RuntimeType, SessionJSON
57
58
  from supervisely.nn.inference.inference import Inference
58
59
  from supervisely.nn.task_type import TaskType
59
60
  from supervisely.nn.training.gui.gui import TrainGUI
61
+ from supervisely.nn.training.gui.utils import generate_task_check_function_js
60
62
  from supervisely.nn.training.loggers import setup_train_logger, train_logger
61
63
  from supervisely.nn.utils import ModelSource, _get_model_name
62
64
  from supervisely.output import set_directory
@@ -1949,11 +1951,15 @@ class TrainApp:
1949
1951
  self.progress_bar_main.hide()
1950
1952
 
1951
1953
  file_info = self._api.file.get_info_by_path(self.team_id, join(remote_dir, "open_app.lnk"))
1954
+
1952
1955
  # Set offline tensorboard button payload
1953
1956
  if is_production():
1954
- self.gui.training_logs.tensorboard_offline_button.payload = {
1955
- "state": {"slyFolder": f"{join(remote_dir, 'logs')}"}
1956
- }
1957
+ remote_log_dir = join(remote_dir, "logs")
1958
+ tb_btn_payload = {"state": {"slyFolder": remote_log_dir}}
1959
+ self.gui.training_logs.tensorboard_offline_button.payload = tb_btn_payload
1960
+ self.gui.training_logs.tensorboard_offline_button.set_check_existing_task_cb(
1961
+ generate_task_check_function_js(remote_log_dir)
1962
+ )
1957
1963
  self.gui.training_logs.tensorboard_offline_button.enable()
1958
1964
 
1959
1965
  return remote_dir, file_info
@@ -2608,6 +2614,10 @@ class TrainApp:
2608
2614
  self.gui.training_process.start_button.loading = False
2609
2615
 
2610
2616
  # Shutdown the app after training is finished
2617
+
2618
+ self.gui.training_logs.tensorboard_button.hide()
2619
+ self.gui.training_logs.tensorboard_offline_button.show()
2620
+ sleep(1) # wait for the button to be shown
2611
2621
  self.app.shutdown()
2612
2622
  except Exception as e:
2613
2623
  message = f"Error occurred during finalizing and uploading training artifacts. {check_logs_text}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.372
3
+ Version: 6.73.374
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -1,6 +1,6 @@
1
1
  supervisely/README.md,sha256=XM-DiMC6To3I9RjQZ0c61905EFRR_jnCUx2q3uNR-X8,3331
2
2
  supervisely/__init__.py,sha256=_qphKFT0_toEQmF5IjB1sWjztbF4lP1tLY29PBJhArY,10917
3
- supervisely/_utils.py,sha256=8R1XgIPwBG7pqwyk93nYExd7SkSyXx9VbQvseQNiT3M,18621
3
+ supervisely/_utils.py,sha256=J0-qYN8YAEGJO4mmE5ErNdRx9mSVEYf5oIgqM4efegU,18926
4
4
  supervisely/function_wrapper.py,sha256=R5YajTQ0GnRp2vtjwfC9hINkzQc0JiyGsu8TER373xY,1912
5
5
  supervisely/sly_logger.py,sha256=z92Vu5hmC0GgTIJO1n6kPDayRW9__8ix8hL6poDZj-Y,6274
6
6
  supervisely/tiny_timer.py,sha256=hkpe_7FE6bsKL79blSs7WBaktuPavEVu67IpEPrfmjE,183
@@ -33,9 +33,9 @@ supervisely/api/image_annotation_tool_api.py,sha256=YcUo78jRDBJYvIjrd-Y6FJAasLta
33
33
  supervisely/api/image_api.py,sha256=zwyHsphaclKFU2a5gpHy6Cas_kpitViSCMV6vcPqR0s,224592
34
34
  supervisely/api/import_storage_api.py,sha256=BDCgmR0Hv6OoiRHLCVPKt3iDxSVlQp1WrnKhAK_Zl84,460
35
35
  supervisely/api/issues_api.py,sha256=BqDJXmNoTzwc3xe6_-mA7FDFC5QQ-ahGbXk_HmpkSeQ,17925
36
- supervisely/api/labeling_job_api.py,sha256=qvfbU8lme_fhTDgTP5UmyL8v3K7otTB6Obt8T2mAFmI,55190
37
- supervisely/api/labeling_queue_api.py,sha256=j56oq5z916pSz85bzuUzuwZYxJR0pRT2KbyxiuCClgk,28427
38
- supervisely/api/module_api.py,sha256=Uly6l7KkB3rS9BHfRyulvNxYUsQ3g_EG-LoS0Ji6sJ8,45301
36
+ supervisely/api/labeling_job_api.py,sha256=G2_BV_WtA2lAhfw_nAQmWmv1P-pwimD0ba9GVKoGjiA,55537
37
+ supervisely/api/labeling_queue_api.py,sha256=ilNjAL1d9NSa9yabQn6E-W26YdtooT3ZGXIFZtGnAvY,30158
38
+ supervisely/api/module_api.py,sha256=u-xm7DEkmIGJjhJKehCAs3w0GiC3xxNeLvQ_hTyGAF4,45363
39
39
  supervisely/api/object_class_api.py,sha256=7-npNFMYjWNtSXYZg6syc6bX56_oCzDU2kFRPGQWCwA,10399
40
40
  supervisely/api/plugin_api.py,sha256=SFm0IlTTOjuHBLUMgG4d4k6U3cWJocE-SVb-f08fwMQ,5286
41
41
  supervisely/api/project_api.py,sha256=WNTMqAa0ZedYesfiZEkZtaFr5huxIpJ8TFYygTnlAWQ,80309
@@ -427,9 +427,9 @@ supervisely/app/widgets/report_thumbnail/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
427
427
  supervisely/app/widgets/report_thumbnail/report_thumbnail.py,sha256=JYEoNi9tXslx9nlxdFcklxk-4ONtb_F46H5FRxZD1p0,2163
428
428
  supervisely/app/widgets/report_thumbnail/template.html,sha256=7dGngqwO_xxWZLOre0f6Vml3B_qXWu0l1P96L3opJ84,429
429
429
  supervisely/app/widgets/run_app_button/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
430
- supervisely/app/widgets/run_app_button/run_app_button.py,sha256=CGX37FLyl7eWtVdWRu-00zgebEmPRS2yfnEkSowH_F8,10011
431
- supervisely/app/widgets/run_app_button/script.js,sha256=SIBDV5CepA34aFuLUPNMsAZiqLqkUq8kP9PQfLp-iAM,1325
432
- supervisely/app/widgets/run_app_button/template.html,sha256=-SX7zZ53ehyfQMg_az3B9dl5_UC3TdvHL9yXNNgsowk,403
430
+ supervisely/app/widgets/run_app_button/run_app_button.py,sha256=cr07jabP1vF-rvH0_swVTuzpWXsvI9tHy_oQbJrHxSU,11044
431
+ supervisely/app/widgets/run_app_button/script.js,sha256=6rlluiW1hbHN7swtNSoFX9Gmrz2U-nRNOwoUpnSBmiw,2736
432
+ supervisely/app/widgets/run_app_button/template.html,sha256=rFIYPC9hl2b9H_LR1Kr_1RCpzfAAd-FBcmTmt75YXnE,511
433
433
  supervisely/app/widgets/scatter_chart/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
434
434
  supervisely/app/widgets/scatter_chart/scatter_chart.py,sha256=nX7fZbWsDiMjOek5FvIHgKbnBwQ-ol_V3XvnoAnz59c,4832
435
435
  supervisely/app/widgets/select/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -994,7 +994,7 @@ supervisely/nn/tracking/__init__.py,sha256=Ld1ed7ZZQZPkhX-5Xr-UbHZx5zLCm2-tInHnP
994
994
  supervisely/nn/tracking/boxmot.py,sha256=H9cQjYGL9nX_TLrfKDChhljTIiE9lffcgbwWCf_4PJU,4277
995
995
  supervisely/nn/tracking/tracking.py,sha256=WNrNm02B1pspA3d_AmzSJ-54RZTqWV2NZiC7FHe88bo,857
996
996
  supervisely/nn/training/__init__.py,sha256=gY4PCykJ-42MWKsqb9kl-skemKa8yB6t_fb5kzqR66U,111
997
- supervisely/nn/training/train_app.py,sha256=D2Fuy1SzoHTqeMWrdLLVLqeZN5Eu6M_CzU85y78na6I,116077
997
+ supervisely/nn/training/train_app.py,sha256=-NbFxj0MMPGJ8ysQcIxYd3j7oKutEcOYL9-9oO-bCiU,116587
998
998
  supervisely/nn/training/gui/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
999
999
  supervisely/nn/training/gui/classes_selector.py,sha256=Bpp-RFDQqcZ0kLJmS6ZnExkdscWwRusvF4vbWjEsKlQ,3926
1000
1000
  supervisely/nn/training/gui/gui.py,sha256=Z68uMPNkOyb70rpxfVDfJuGSzcoOhrqqDog8PABF2JQ,43312
@@ -1004,9 +1004,9 @@ supervisely/nn/training/gui/model_selector.py,sha256=I6KRKyylpwUEC3CApEnzDKkWe5x
1004
1004
  supervisely/nn/training/gui/tags_selector.py,sha256=ZirVXm5NNuIDjXO3wuHDnpYTWgFVLn-W7voBudh5bP0,3772
1005
1005
  supervisely/nn/training/gui/train_val_splits_selector.py,sha256=V8aMe0l-CaoHxP0y6GeCBGDMd7L3epQ3KqeFsMY43rs,11191
1006
1006
  supervisely/nn/training/gui/training_artifacts.py,sha256=c0GH70ZByvnL413KWHjSKcSX8V5DStXM5sjFVZafSZo,10519
1007
- supervisely/nn/training/gui/training_logs.py,sha256=fXj1Cszu7Qi4p8tNdBPqwet08I4xcphB5jbTPjCDmVk,4851
1007
+ supervisely/nn/training/gui/training_logs.py,sha256=GgEQMj9p98Z3p2b_-3BkHOhY7WQYELxctsRKmkbg3JY,4966
1008
1008
  supervisely/nn/training/gui/training_process.py,sha256=2F65cuu5ypKWkdaO4uVpNLMkwXjM8dpprd7Km5aedds,3192
1009
- supervisely/nn/training/gui/utils.py,sha256=EO629fSOwxOsiXL7mr1EXTiKKMIg7xgVm3jtCnF4r7Q,4268
1009
+ supervisely/nn/training/gui/utils.py,sha256=cEOsYItxgGTGKxFAvn7zQcTpwHgcGRO_UNGBn8idMUI,4983
1010
1010
  supervisely/nn/training/loggers/__init__.py,sha256=DOqR-4NJv25C4Y1HCWggvGNM5mgo1CbwQOdvROOL-60,777
1011
1011
  supervisely/nn/training/loggers/base_train_logger.py,sha256=Gf_TKwSfQdSVG6P3wAeWf5t2_EJWJqOPqt_TsJ5jpBY,1914
1012
1012
  supervisely/nn/training/loggers/tensorboard_logger.py,sha256=s6dNFHIaucRTRMEdDM8mHT7v8bUdl13oDK78kPeCW8U,1116
@@ -1097,9 +1097,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
1097
1097
  supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
1098
1098
  supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
1099
1099
  supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
1100
- supervisely-6.73.372.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1101
- supervisely-6.73.372.dist-info/METADATA,sha256=XPL2_lh1M9AS2npHgR0X2gs4DTWhMwvycMQuLo3wZws,35154
1102
- supervisely-6.73.372.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
1103
- supervisely-6.73.372.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1104
- supervisely-6.73.372.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1105
- supervisely-6.73.372.dist-info/RECORD,,
1100
+ supervisely-6.73.374.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1101
+ supervisely-6.73.374.dist-info/METADATA,sha256=CZQRzlek6lQZ0EeIc-BYmKKPqE-p-nVIGMMm7eh4Aws,35154
1102
+ supervisely-6.73.374.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
1103
+ supervisely-6.73.374.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1104
+ supervisely-6.73.374.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1105
+ supervisely-6.73.374.dist-info/RECORD,,