supervisely 6.73.390__py3-none-any.whl → 6.73.392__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 (34) hide show
  1. supervisely/app/widgets/experiment_selector/experiment_selector.py +21 -3
  2. supervisely/app/widgets/experiment_selector/template.html +49 -70
  3. supervisely/app/widgets/report_thumbnail/report_thumbnail.py +19 -4
  4. supervisely/decorators/profile.py +20 -0
  5. supervisely/nn/benchmark/utils/detection/utlis.py +7 -0
  6. supervisely/nn/experiments.py +4 -0
  7. supervisely/nn/inference/gui/serving_gui_template.py +71 -11
  8. supervisely/nn/inference/inference.py +108 -6
  9. supervisely/nn/training/gui/classes_selector.py +246 -27
  10. supervisely/nn/training/gui/gui.py +318 -234
  11. supervisely/nn/training/gui/hyperparameters_selector.py +2 -2
  12. supervisely/nn/training/gui/model_selector.py +42 -1
  13. supervisely/nn/training/gui/tags_selector.py +1 -1
  14. supervisely/nn/training/gui/train_val_splits_selector.py +8 -7
  15. supervisely/nn/training/gui/training_artifacts.py +10 -1
  16. supervisely/nn/training/gui/training_process.py +17 -1
  17. supervisely/nn/training/train_app.py +227 -72
  18. supervisely/template/__init__.py +2 -0
  19. supervisely/template/base_generator.py +90 -0
  20. supervisely/template/experiment/__init__.py +0 -0
  21. supervisely/template/experiment/experiment.html.jinja +537 -0
  22. supervisely/template/experiment/experiment_generator.py +996 -0
  23. supervisely/template/experiment/header.html.jinja +154 -0
  24. supervisely/template/experiment/sidebar.html.jinja +240 -0
  25. supervisely/template/experiment/sly-style.css +397 -0
  26. supervisely/template/experiment/template.html.jinja +18 -0
  27. supervisely/template/extensions.py +172 -0
  28. supervisely/template/template_renderer.py +253 -0
  29. {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/METADATA +3 -1
  30. {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/RECORD +34 -23
  31. {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/LICENSE +0 -0
  32. {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/WHEEL +0 -0
  33. {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/entry_points.txt +0 -0
  34. {supervisely-6.73.390.dist-info → supervisely-6.73.392.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,397 @@
1
+ .experiment-body .sly-markdown-widget .markdown-body {
2
+ padding: 0;
3
+ font-family: inherit;
4
+ }
5
+
6
+ .experiment-body .sly-markdown-widget .markdown-body h2 {
7
+ font-size: 18px;
8
+ font-weight: 600;
9
+ margin-bottom: 0px;
10
+ border: 0;
11
+ }
12
+
13
+ .experiment-body .sly-markdown-widget .markdown-body h3 {
14
+ color: #949bab;
15
+ font-size: 18px;
16
+ margin-bottom: 7px;
17
+ }
18
+
19
+ .experiment-body .sly-markdown-widget .markdown-body p {
20
+ margin-bottom: 12px;
21
+ }
22
+
23
+ .experiment-body .section {
24
+ margin-bottom: 30px;
25
+ scroll-margin-top: 20px;
26
+ padding-top: 10px;
27
+ }
28
+
29
+ .experiment-body .overview-info-block {
30
+ background: #f4f7fb;
31
+ border-radius: 12px;
32
+ padding: 20px;
33
+ margin-bottom: 20px;
34
+ }
35
+
36
+ .experiment-body .width-fit-content {
37
+ width: fit-content;
38
+ }
39
+
40
+ .experiment-body .main-content {
41
+ flex-grow: 1;
42
+ margin-right: 20px;
43
+ }
44
+
45
+ .experiment-body .buttons-container {
46
+ display: flex;
47
+ flex-wrap: wrap;
48
+ gap: 10px;
49
+ margin-bottom: 20px;
50
+ }
51
+
52
+ .experiment-body hr {
53
+ display: none
54
+ }
55
+
56
+ .experiment-body blockquote {
57
+ margin: 15px 0 0;
58
+ }
59
+
60
+ .experiment-body table {
61
+ width: 100%;
62
+ border-collapse: collapse;
63
+ margin-bottom: 20px;
64
+ }
65
+
66
+ .experiment-body table th,
67
+ .experiment-body table td {
68
+ border: 1px solid #e0e0e0;
69
+ padding: 8px 12px;
70
+ text-align: left;
71
+ }
72
+
73
+ .experiment-body table th {
74
+ background-color: #f4f7fb;
75
+ }
76
+
77
+ .experiment-body .table {
78
+ width: 100%;
79
+ border-collapse: collapse;
80
+ margin-bottom: 20px;
81
+ /* box-shadow: 0 2px 6px rgba(0,0,0,0.05); */
82
+ border-radius: 6px;
83
+ overflow: hidden;
84
+ }
85
+
86
+ .experiment-body .table th {
87
+ background-color: #f4f7fb;
88
+ font-weight: 600;
89
+ color: #333;
90
+ padding: 12px 15px;
91
+ text-align: left;
92
+ border-bottom: 2px solid #e0e0e0;
93
+ }
94
+
95
+ .experiment-body .table td {
96
+ padding: 10px 15px;
97
+ border-bottom: 1px solid #e9ecef;
98
+ }
99
+
100
+ .experiment-body .table tr:hover {
101
+ background-color: #f8f9fa;
102
+ }
103
+
104
+ .experiment-body .links-list,
105
+ .experiment-body .overview-list,
106
+ .experiment-body .buttons-list {
107
+ list-style-type: none;
108
+ padding: 0;
109
+ margin: 0 0 20px 0;
110
+ }
111
+
112
+ .experiment-body .links-list li,
113
+ .experiment-body .overview-list li,
114
+ .experiment-body .buttons-list li {
115
+ margin-bottom: 8px;
116
+ position: relative;
117
+ padding-left: 8px;
118
+ display: flex;
119
+ align-items: flex-start;
120
+ }
121
+
122
+ .experiment-body .links-list li:before,
123
+ .experiment-body .buttons-list li:before {
124
+ content: "•";
125
+ color: #1890ff;
126
+ display: inline-block;
127
+ width: 15px;
128
+ margin-right: 10px;
129
+ }
130
+
131
+ .experiment-body .overview-list li:before {
132
+ content: "";
133
+ display: none;
134
+ }
135
+
136
+ .experiment-body .link-icon,
137
+ .experiment-body .button-icon {
138
+ margin-right: 8px;
139
+ }
140
+
141
+ .experiment-body .overview-list .label {
142
+ font-weight: 600;
143
+ margin-right: 8px;
144
+ min-width: 120px;
145
+ display: inline-block;
146
+ }
147
+
148
+ /* Code */
149
+ .experiment-body .code-block {
150
+ background-color: #f5f5f5;
151
+ border-radius: 6px;
152
+ padding: 15px;
153
+ margin-bottom: 20px;
154
+ overflow-x: auto;
155
+ }
156
+
157
+ .experiment-body details {
158
+ border-radius: 6px;
159
+ overflow: hidden;
160
+ margin-bottom: 20px;
161
+ }
162
+
163
+ .experiment-body details summary {
164
+ padding: 12px 15px;
165
+ background-color: #f4f7fb;
166
+ border-radius: 6px;
167
+ cursor: pointer;
168
+ font-weight: 600;
169
+ transition: background-color 0.2s;
170
+ width: fit-content;
171
+ }
172
+
173
+ .experiment-body details summary:hover {
174
+ background-color: #e6edf7;
175
+ }
176
+
177
+ .experiment-body details[open] summary {
178
+ border-bottom-left-radius: 0;
179
+ border-bottom-right-radius: 0;
180
+ margin-bottom: 10px;
181
+ }
182
+
183
+ /* Classes overview styles */
184
+ .classes-overview {
185
+ margin-bottom: 30px;
186
+ }
187
+
188
+ .class-tags {
189
+ display: flex;
190
+ flex-wrap: wrap;
191
+ gap: 8px;
192
+ margin-top: 12px;
193
+ }
194
+
195
+ .class-tag {
196
+ background: #e3e8ef;
197
+ color: #434a53;
198
+ padding: 3px 7px;
199
+ border-radius: 4px;
200
+ font-size: 12px;
201
+ font-weight: 400;
202
+ }
203
+
204
+
205
+ .experiment-main-wrapper {
206
+ display: flex;
207
+ }
208
+
209
+ .experiment-main-content .main-content.markdown-body {
210
+ font-size: 14px;
211
+ font-family: inherit;
212
+ }
213
+
214
+ .experiment-main-content .main-content.markdown-body h2 {
215
+ font-size: 18px;
216
+ font-weight: 700;
217
+ /* border: 0;
218
+ padding: 0; */
219
+ }
220
+
221
+ .experiment-main-content .main-content.markdown-body h3 {
222
+ font-size: 16px;
223
+ font-weight: 700;
224
+ border: 0;
225
+ }
226
+
227
+ .experiment-main-content .main-content.markdown-body .img-grid-gallery-v2-header {
228
+ font-size: 13px;
229
+ }
230
+
231
+ /*********************** Header ***********************/
232
+
233
+ .experiment-body .experiment-info-header {
234
+ background: #f8fafc;
235
+ border-radius: 6px;
236
+ font-size: 14px;
237
+ }
238
+
239
+ .experiment-body .experiment-info-header h1 {
240
+ margin: 0;
241
+ font-size: 18px;
242
+ font-weight: 700;
243
+ padding: 0;
244
+ border: 0;
245
+ }
246
+
247
+ .experiment-body .experiment-info-header ul {
248
+ list-style: none;
249
+ padding: 0;
250
+ margin: 0;
251
+ }
252
+
253
+ .experiment-body .experiment-info-header .experiment-info-subheader {
254
+ display: flex;
255
+ background: #f1f5f9;
256
+ padding: 15px 20px;
257
+ justify-content: space-between;
258
+ align-items: center;
259
+ border-radius: 6px 6px 0 0;
260
+ }
261
+
262
+ .experiment-body .experiment-info-header .experiment-info-subheader-body {
263
+ padding: 15px 20px;
264
+ display: flex;
265
+ gap: 30px;
266
+ }
267
+
268
+ .experiment-body .experiment-info-header .experiment-info-subheader-body h2 {
269
+ border: 0;
270
+ margin: 0;
271
+ font-size: 16px;
272
+ font-weight: 700;
273
+ margin-right: 5px;
274
+ }
275
+
276
+ .experiment-body .experiment-info-header .experiment-info-subheader-body ul strong {
277
+ width: 100px;
278
+ }
279
+
280
+ .experiment-body .experiment-info-header .experiment-info-subheader-block {
281
+ padding-right: 30px;
282
+ border-right: 1px solid #dde4ef;
283
+ }
284
+
285
+ /*.experiment-body .experiment-info-header .experiment-info-subheader-block:nth-last-child(2) { border: none; flex: 1; }*/
286
+
287
+ .experiment-body .experiment-info-header .experiment-info-subheader-block:last-child {
288
+ border: none;
289
+ }
290
+
291
+ .experiment-body .experiment-info-header .experiment-info-subheader-block .experiment-info-subheader-mini-title {
292
+ display: flex;
293
+ align-items: center;
294
+ gap: 3px;
295
+ margin: 0 0 6px;
296
+ }
297
+
298
+ .experiment-body .experiment-info-header .experiment-info-subheader-block .experiment-info-subheader-mini-title a {
299
+ padding: 2px 6px;
300
+ border: 1px solid #ccd3d9;
301
+ border-radius: 6px;
302
+ font-size: 12px;
303
+ cursor: pointer;
304
+ background: white;
305
+ /*color: #1a6cdb;*/
306
+ color: black;
307
+ margin-left: 3px;
308
+ margin-top: -2px;
309
+ }
310
+
311
+ .experiment-body .experiment-info-header .experiment-info-buttons {
312
+ display: flex;
313
+ gap: 5px;
314
+ align-items: center;
315
+ }
316
+
317
+ .experiment-body .experiment-info-header .experiment-info-buttons a {
318
+ display: flex;
319
+ gap: 5px;
320
+ align-items: center;
321
+ background: white;
322
+ padding: 7px 13px;
323
+ border: 1px solid #ccd3d9;
324
+ border-radius: 6px;
325
+ font-size: 13px;
326
+ font-weight: 600;
327
+ cursor: pointer;
328
+ }
329
+
330
+ .experiment-body .experiment-info-header .experiment-info-buttons a.primary {
331
+ background: black;
332
+ color: white;
333
+ }
334
+
335
+ .experiment-body .experiment-info-header .experiment-info-buttons img {
336
+ height: 16px;
337
+ width: auto;
338
+ background: transparent;
339
+ }
340
+
341
+ /*********************** Metrics ***********************/
342
+
343
+ .experiment-body .experiment-metric {
344
+ font-size: 13px;
345
+ display: flex;
346
+ align-items: center;
347
+ justify-content: space-between;
348
+ }
349
+
350
+ .experiment-body .experiment-metric .experiment-label {
351
+ width: 100px;
352
+ font-weight: 600;
353
+ }
354
+
355
+ .experiment-body .experiment-metric .experiment-value {
356
+ margin-right: 5px;
357
+ text-align: right;
358
+ }
359
+
360
+ .experiment-body .experiment-progress-bar {
361
+ background: #eee;
362
+ height: 6px;
363
+ border-radius: 6px;
364
+ overflow: hidden;
365
+ width: 90px;
366
+ }
367
+
368
+ .experiment-body .experiment-progress {
369
+ height: 100%;
370
+ background: #28a745;
371
+ }
372
+
373
+ .experiment-body .experiment-info-header .experiment-info-subheader-footer-menu {
374
+ display: flex;
375
+ gap: 5px;
376
+ margin: 0px 20px;
377
+ padding-top: 5px;
378
+ border-top: 1px solid #dde4ef;
379
+ font-size: 14px;
380
+ }
381
+
382
+ .experiment-body .experiment-info-header .experiment-info-subheader-footer-menu a {
383
+ line-height: 36px;
384
+ padding: 0 7px;
385
+ color: black;
386
+ border-bottom: 2px solid transparent;
387
+ }
388
+
389
+ .experiment-body .experiment-info-header .experiment-info-subheader-footer-menu a:hover {
390
+ text-decoration: none;
391
+ }
392
+
393
+ .experiment-body .experiment-info-header .experiment-info-subheader-footer-menu a.active {
394
+ border-color: #20a0ff;
395
+ font-weight: 500;
396
+ color: #20a0ff;
397
+ }
@@ -0,0 +1,18 @@
1
+ <div class="experiment-body">
2
+ <sly-style>
3
+ {% include "sly-style.css" %}
4
+ </sly-style>
5
+
6
+ <div class="experiment-main-wrapper">
7
+ <!-- Main content -->
8
+ <div class="experiment-main-content">
9
+ <div class="main-content markdown-body">
10
+ {% include "header.html.jinja" %}
11
+
12
+ {% markdown %}
13
+ {% include "experiment.html.jinja" %}
14
+ {% endmarkdown %}
15
+ </div>
16
+ </div>
17
+ </div>
18
+ </div>
@@ -0,0 +1,172 @@
1
+ import json
2
+ import re
3
+ import textwrap
4
+
5
+ try:
6
+ import markdown # type: ignore
7
+ except ImportError: # pragma: no cover
8
+ markdown = None # type: ignore
9
+ from jinja2.ext import Extension
10
+ from jinja2.nodes import CallBlock
11
+
12
+
13
+ class MarkdownExtension(Extension):
14
+ EXTENSIONS = [
15
+ "admonition",
16
+ "attr_list",
17
+ "smarty",
18
+ "tables",
19
+ "pymdownx.betterem",
20
+ "pymdownx.caret",
21
+ "pymdownx.details",
22
+ "pymdownx.emoji",
23
+ "pymdownx.keys",
24
+ "pymdownx.magiclink",
25
+ "pymdownx.mark",
26
+ "pymdownx.smartsymbols",
27
+ "pymdownx.superfences",
28
+ "pymdownx.tabbed",
29
+ "pymdownx.tasklist",
30
+ "pymdownx.tilde",
31
+ "pymdownx.highlight",
32
+ ]
33
+
34
+ EXTENSION_CONFIGS = {
35
+ "pymdownx.highlight": {
36
+ "use_pygments": True,
37
+ "noclasses": True,
38
+ # "linenums": True,
39
+ # "linenums_style": "pymdownx-inline",
40
+ },
41
+ }
42
+ tags = set(["markdown"])
43
+
44
+ def __init__(self, environment):
45
+ super(MarkdownExtension, self).__init__(environment)
46
+ if markdown is None:
47
+ raise ImportError("markdown library is required for MarkdownExtension but is not installed.")
48
+
49
+ environment.extend(
50
+ markdowner=markdown.Markdown(
51
+ extensions=self.EXTENSIONS, extension_configs=self.EXTENSION_CONFIGS
52
+ )
53
+ )
54
+
55
+ def parse(self, parser):
56
+ lineno = next(parser.stream).lineno
57
+ body = parser.parse_statements(["name:endmarkdown"], drop_needle=True)
58
+ return CallBlock(self.call_method("_render_markdown"), [], [], body).set_lineno(lineno)
59
+
60
+ def _render_markdown(self, caller):
61
+ text = caller()
62
+ text = self._dedent(text)
63
+ return self.environment.markdowner.convert(text)
64
+
65
+ def _dedent(self, text):
66
+ return textwrap.dedent(text.strip("\n"))
67
+
68
+
69
+ class AutoSidebarExtension(Extension):
70
+ tags = {"autosidebar"}
71
+
72
+ def parse(self, parser):
73
+ lineno = next(parser.stream).lineno
74
+ return CallBlock(self.call_method("_placeholder"), [], [], []).set_lineno(lineno)
75
+
76
+ def _placeholder(self, caller):
77
+ return "<!--AUTOSIDEBAR_PLACEHOLDER-->\n"
78
+
79
+
80
+ def _slugify(text: str) -> str:
81
+ """Simple slugify helper (kebab-case)."""
82
+ text = text.lower()
83
+ text = re.sub(r"[^a-z0-9]+", "-", text)
84
+ text = re.sub(r"-+", "-", text).strip("-")
85
+ return text or "tab"
86
+
87
+
88
+ class TabExtension(Extension):
89
+ """
90
+ Internal helper extension. Each `{% tab title="X" %} ... {% endtab %}` inside a
91
+ `{% tabs %} ... {% endtabs %}` block will register its content in a temporary
92
+ buffer on the Jinja2 `Environment` (``_tab_buffer``).
93
+ The buffer is consumed by the outer `TabsExtension` which renders the final
94
+ HTML with `<sly-iw-tabs>` component.
95
+ """
96
+
97
+ tags = {"tab"}
98
+
99
+ def parse(self, parser):
100
+ lineno = next(parser.stream).lineno
101
+ # Expect: tab title="Some Title"
102
+ parser.stream.expect("name:title")
103
+ parser.stream.expect("assign") # '=' symbol
104
+ title_expr = parser.parse_expression()
105
+ body = parser.parse_statements(["name:endtab"], drop_needle=True)
106
+ return CallBlock(self.call_method("_render_tab", [title_expr]), [], [], body).set_lineno(
107
+ lineno
108
+ )
109
+
110
+ def _render_tab(self, title: str, caller):
111
+ raw_content = caller()
112
+ # content_html = self.environment.markdowner.convert(raw_content)
113
+
114
+ buf = getattr(self.environment, "_tab_buffer", None)
115
+ if buf is not None:
116
+ buf.append((title, raw_content))
117
+ # buf.append((title, content_html))
118
+ return ""
119
+
120
+
121
+ class TabsExtension(Extension):
122
+ """
123
+ Implements a GitBook-style tabs syntax:
124
+
125
+ ```
126
+ {% tabs %}
127
+ {% tab title="Windows" %}
128
+ Windows content
129
+ {% endtab %}
130
+ {% tab title="Linux" %}
131
+ Linux content
132
+ {% endtab %}
133
+ {% endtabs %}
134
+ ```
135
+ """
136
+
137
+ tags = {"tabs"}
138
+
139
+ def parse(self, parser):
140
+ lineno = next(parser.stream).lineno
141
+ body = parser.parse_statements(["name:endtabs"], drop_needle=True)
142
+ return CallBlock(self.call_method("_render_tabs"), [], [], body).set_lineno(lineno)
143
+
144
+ def _render_tabs(self, caller):
145
+ # Prepare a buffer for nested tab blocks
146
+ self.environment._tab_buffer = []
147
+ caller() # Render inner content – `TabExtension` will fill the buffer
148
+ tabs_data = self.environment._tab_buffer
149
+ # Clean up
150
+ delattr(self.environment, "_tab_buffer")
151
+
152
+ if not tabs_data:
153
+ # Nothing collected – return original caller() content
154
+ return ""
155
+
156
+ # Build tab definitions
157
+ tab_defs = []
158
+ rendered_templates = []
159
+ for title, content in tabs_data:
160
+ slug = _slugify(title)
161
+ tab_defs.append({"name": slug, "title": title})
162
+ rendered_templates.append(f"<template #{slug}>\n{content}\n</template>")
163
+
164
+ tabs_json = json.dumps(tab_defs)
165
+ html_parts = [
166
+ "<div>",
167
+ f"<sly-iw-tabs :tabs='{tabs_json}' :defaultIndex='0' :command='command' :data='data'>",
168
+ *rendered_templates,
169
+ "</sly-iw-tabs>",
170
+ "</div>",
171
+ ]
172
+ return "\n".join(html_parts)