supervisely 6.73.348__py3-none-any.whl → 6.73.350__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/api/entity_annotation/figure_api.py +208 -19
- supervisely/app/fastapi/index.html +2 -1
- supervisely/app/fastapi/templating.py +1 -1
- {supervisely-6.73.348.dist-info → supervisely-6.73.350.dist-info}/METADATA +1 -1
- {supervisely-6.73.348.dist-info → supervisely-6.73.350.dist-info}/RECORD +9 -9
- {supervisely-6.73.348.dist-info → supervisely-6.73.350.dist-info}/LICENSE +0 -0
- {supervisely-6.73.348.dist-info → supervisely-6.73.350.dist-info}/WHEEL +0 -0
- {supervisely-6.73.348.dist-info → supervisely-6.73.350.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.348.dist-info → supervisely-6.73.350.dist-info}/top_level.txt +0 -0
|
@@ -23,7 +23,7 @@ import numpy as np
|
|
|
23
23
|
from requests_toolbelt import MultipartDecoder, MultipartEncoder
|
|
24
24
|
from tqdm import tqdm
|
|
25
25
|
|
|
26
|
-
from supervisely._utils import batched
|
|
26
|
+
from supervisely._utils import batched, logger, run_coroutine
|
|
27
27
|
from supervisely.api.module_api import ApiField, ModuleApi, RemoveableBulkModuleApi
|
|
28
28
|
from supervisely.geometry.rectangle import Rectangle
|
|
29
29
|
from supervisely.video_annotation.key_id_map import KeyIdMap
|
|
@@ -473,24 +473,24 @@ class FigureApi(RemoveableBulkModuleApi):
|
|
|
473
473
|
:rtype: :class: `Dict[int, List[FigureInfo]]`
|
|
474
474
|
"""
|
|
475
475
|
fields = [
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
476
|
+
ApiField.ID,
|
|
477
|
+
ApiField.CREATED_AT,
|
|
478
|
+
ApiField.UPDATED_AT,
|
|
479
|
+
ApiField.IMAGE_ID,
|
|
480
|
+
ApiField.OBJECT_ID,
|
|
481
|
+
ApiField.CLASS_ID,
|
|
482
|
+
ApiField.PROJECT_ID,
|
|
483
|
+
ApiField.DATASET_ID,
|
|
484
|
+
ApiField.GEOMETRY,
|
|
485
|
+
ApiField.GEOMETRY_TYPE,
|
|
486
|
+
ApiField.GEOMETRY_META,
|
|
487
|
+
ApiField.TAGS,
|
|
488
|
+
ApiField.META,
|
|
489
|
+
ApiField.AREA,
|
|
490
|
+
ApiField.PRIORITY,
|
|
491
491
|
]
|
|
492
492
|
if skip_geometry is True:
|
|
493
|
-
fields = [x for x in fields if x !=
|
|
493
|
+
fields = [x for x in fields if x != ApiField.GEOMETRY]
|
|
494
494
|
|
|
495
495
|
if image_ids is None:
|
|
496
496
|
filters = []
|
|
@@ -498,8 +498,8 @@ class FigureApi(RemoveableBulkModuleApi):
|
|
|
498
498
|
filters = [
|
|
499
499
|
{
|
|
500
500
|
ApiField.FIELD: ApiField.ENTITY_ID,
|
|
501
|
-
|
|
502
|
-
|
|
501
|
+
ApiField.OPERATOR: "in",
|
|
502
|
+
ApiField.VALUE: image_ids,
|
|
503
503
|
}
|
|
504
504
|
]
|
|
505
505
|
data = {
|
|
@@ -784,3 +784,192 @@ class FigureApi(RemoveableBulkModuleApi):
|
|
|
784
784
|
|
|
785
785
|
if tasks:
|
|
786
786
|
await asyncio.gather(*tasks)
|
|
787
|
+
|
|
788
|
+
async def download_async(
|
|
789
|
+
self,
|
|
790
|
+
dataset_id: int,
|
|
791
|
+
image_ids: Optional[List[int]] = None,
|
|
792
|
+
skip_geometry: bool = False,
|
|
793
|
+
semaphore: Optional[asyncio.Semaphore] = None,
|
|
794
|
+
log_progress: bool = True,
|
|
795
|
+
) -> Dict[int, List[FigureInfo]]:
|
|
796
|
+
"""
|
|
797
|
+
Asynchronously download figures for the given dataset ID. Can be filtered by image IDs.
|
|
798
|
+
This method is significantly faster than the synchronous version for large datasets.
|
|
799
|
+
|
|
800
|
+
:param dataset_id: Dataset ID in Supervisely.
|
|
801
|
+
:type dataset_id: int
|
|
802
|
+
:param image_ids: Specify the list of image IDs within the given dataset ID. If image_ids is None, the method returns all possible pairs of images with figures.
|
|
803
|
+
:type image_ids: List[int], optional
|
|
804
|
+
:param skip_geometry: Skip the download of figure geometry. May be useful for a significant api request speed increase in the large datasets.
|
|
805
|
+
:type skip_geometry: bool
|
|
806
|
+
:param semaphore: Semaphore to limit the number of concurrent downloads.
|
|
807
|
+
:type semaphore: Optional[asyncio.Semaphore], optional
|
|
808
|
+
:param log_progress: If True, log the progress of the download.
|
|
809
|
+
:type log_progress: bool, optional
|
|
810
|
+
:return: A dictionary where keys are image IDs and values are lists of figures.
|
|
811
|
+
:rtype: Dict[int, List[FigureInfo]]
|
|
812
|
+
|
|
813
|
+
:Usage example:
|
|
814
|
+
|
|
815
|
+
.. code-block:: python
|
|
816
|
+
|
|
817
|
+
import supervisely as sly
|
|
818
|
+
|
|
819
|
+
os.environ['SERVER_ADDRESS'] = 'https://app.supervisely.com'
|
|
820
|
+
os.environ['API_TOKEN'] = 'Your Supervisely API Token'
|
|
821
|
+
api = sly.Api.from_env()
|
|
822
|
+
|
|
823
|
+
dataset_id = 12345
|
|
824
|
+
download_coroutine = api.image.figure.download_async(dataset_id)
|
|
825
|
+
figures = sly.run_coroutine(download_coroutine)
|
|
826
|
+
"""
|
|
827
|
+
fields = [
|
|
828
|
+
ApiField.ID,
|
|
829
|
+
ApiField.CREATED_AT,
|
|
830
|
+
ApiField.UPDATED_AT,
|
|
831
|
+
ApiField.IMAGE_ID,
|
|
832
|
+
ApiField.OBJECT_ID,
|
|
833
|
+
ApiField.CLASS_ID,
|
|
834
|
+
ApiField.PROJECT_ID,
|
|
835
|
+
ApiField.DATASET_ID,
|
|
836
|
+
ApiField.GEOMETRY,
|
|
837
|
+
ApiField.GEOMETRY_TYPE,
|
|
838
|
+
ApiField.GEOMETRY_META,
|
|
839
|
+
ApiField.TAGS,
|
|
840
|
+
ApiField.META,
|
|
841
|
+
ApiField.AREA,
|
|
842
|
+
ApiField.PRIORITY,
|
|
843
|
+
]
|
|
844
|
+
if skip_geometry is True:
|
|
845
|
+
fields = [x for x in fields if x != ApiField.GEOMETRY]
|
|
846
|
+
|
|
847
|
+
if image_ids is None:
|
|
848
|
+
filters = []
|
|
849
|
+
else:
|
|
850
|
+
filters = [
|
|
851
|
+
{
|
|
852
|
+
ApiField.FIELD: ApiField.ENTITY_ID,
|
|
853
|
+
ApiField.OPERATOR: "in",
|
|
854
|
+
ApiField.VALUE: image_ids,
|
|
855
|
+
}
|
|
856
|
+
]
|
|
857
|
+
|
|
858
|
+
data = {
|
|
859
|
+
ApiField.DATASET_ID: dataset_id,
|
|
860
|
+
ApiField.FIELDS: fields,
|
|
861
|
+
ApiField.FILTER: filters,
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
# Get first page to determine total pages
|
|
865
|
+
if semaphore is None:
|
|
866
|
+
semaphore = self._api.get_default_semaphore()
|
|
867
|
+
images_figures = defaultdict(list)
|
|
868
|
+
pages_count = None
|
|
869
|
+
total = 0
|
|
870
|
+
tasks = []
|
|
871
|
+
|
|
872
|
+
async def _get_page(page_data, page_num):
|
|
873
|
+
async with semaphore:
|
|
874
|
+
response = await self._api.post_async("figures.list", page_data)
|
|
875
|
+
response_json = response.json()
|
|
876
|
+
nonlocal pages_count, total
|
|
877
|
+
pages_count = response_json["pagesCount"]
|
|
878
|
+
if page_num == 1:
|
|
879
|
+
total = response_json["total"]
|
|
880
|
+
|
|
881
|
+
page_figures = []
|
|
882
|
+
for info in response_json["entities"]:
|
|
883
|
+
figure_info = self._convert_json_info(info, True)
|
|
884
|
+
page_figures.append(figure_info)
|
|
885
|
+
return page_figures
|
|
886
|
+
|
|
887
|
+
# Get first page
|
|
888
|
+
data[ApiField.PAGE] = 1
|
|
889
|
+
first_page_figures = await _get_page(data, 1)
|
|
890
|
+
|
|
891
|
+
if log_progress:
|
|
892
|
+
progress_cb = tqdm(total=total, desc="Downloading figures")
|
|
893
|
+
|
|
894
|
+
for figure in first_page_figures:
|
|
895
|
+
images_figures[figure.entity_id].append(figure)
|
|
896
|
+
if log_progress:
|
|
897
|
+
progress_cb.update(1)
|
|
898
|
+
|
|
899
|
+
# Get rest of the pages in parallel
|
|
900
|
+
if pages_count > 1:
|
|
901
|
+
for page in range(2, pages_count + 1):
|
|
902
|
+
page_data = data.copy()
|
|
903
|
+
page_data[ApiField.PAGE] = page
|
|
904
|
+
tasks.append(asyncio.create_task(_get_page(page_data, page)))
|
|
905
|
+
|
|
906
|
+
for task in asyncio.as_completed(tasks):
|
|
907
|
+
page_figures = await task
|
|
908
|
+
for figure in page_figures:
|
|
909
|
+
images_figures[figure.entity_id].append(figure)
|
|
910
|
+
if log_progress:
|
|
911
|
+
progress_cb.update(1)
|
|
912
|
+
|
|
913
|
+
return dict(images_figures)
|
|
914
|
+
|
|
915
|
+
def download_fast(
|
|
916
|
+
self,
|
|
917
|
+
dataset_id: int,
|
|
918
|
+
image_ids: Optional[List[int]] = None,
|
|
919
|
+
skip_geometry: bool = False,
|
|
920
|
+
semaphore: Optional[asyncio.Semaphore] = None,
|
|
921
|
+
log_progress: bool = True,
|
|
922
|
+
) -> Dict[int, List[FigureInfo]]:
|
|
923
|
+
"""
|
|
924
|
+
Download figures for the given dataset ID. Can be filtered by image IDs.
|
|
925
|
+
This method is significantly faster than the synchronous version for large datasets and
|
|
926
|
+
is designed to be used in an asynchronous context.
|
|
927
|
+
Will fallback to the synchronous version if async fails.
|
|
928
|
+
|
|
929
|
+
:param dataset_id: Dataset ID in Supervisely.
|
|
930
|
+
:type dataset_id: int
|
|
931
|
+
:param image_ids: Specify the list of image IDs within the given dataset ID. If image_ids is None, the method returns all possible pairs of images with figures.
|
|
932
|
+
:type image_ids: List[int], optional
|
|
933
|
+
:param skip_geometry: Skip the download of figure geometry. May be useful for a significant api request speed increase in the large datasets.
|
|
934
|
+
:type skip_geometry: bool
|
|
935
|
+
:param semaphore: Semaphore to limit the number of concurrent downloads.
|
|
936
|
+
:type semaphore: Optional[asyncio.Semaphore], optional
|
|
937
|
+
:param log_progress: If True, log the progress of the download.
|
|
938
|
+
:type log_progress: bool, optional
|
|
939
|
+
|
|
940
|
+
:return: A dictionary where keys are image IDs and values are lists of figures.
|
|
941
|
+
:rtype: Dict[int, List[FigureInfo]]
|
|
942
|
+
|
|
943
|
+
:Usage example:
|
|
944
|
+
|
|
945
|
+
.. code-block:: python
|
|
946
|
+
|
|
947
|
+
import supervisely as sly
|
|
948
|
+
|
|
949
|
+
os.environ['SERVER_ADDRESS'] = 'https://app.supervisely.com'
|
|
950
|
+
os.environ['API_TOKEN'] = 'Your Supervisely API Token'
|
|
951
|
+
api = sly.Api.from_env()
|
|
952
|
+
|
|
953
|
+
dataset_id = 12345
|
|
954
|
+
figures = api.image.figure.download_fast(dataset_id)
|
|
955
|
+
"""
|
|
956
|
+
try:
|
|
957
|
+
return run_coroutine(
|
|
958
|
+
self.download_async(
|
|
959
|
+
dataset_id=dataset_id,
|
|
960
|
+
image_ids=image_ids,
|
|
961
|
+
skip_geometry=skip_geometry,
|
|
962
|
+
semaphore=semaphore,
|
|
963
|
+
log_progress=log_progress,
|
|
964
|
+
)
|
|
965
|
+
)
|
|
966
|
+
except Exception:
|
|
967
|
+
# Fallback to the synchronous version if async fails
|
|
968
|
+
logger.debug("Async download of figures is failed, falling back to sync download.")
|
|
969
|
+
if log_progress:
|
|
970
|
+
logger.debug("Downloading figures without progress bar.")
|
|
971
|
+
return self.download(
|
|
972
|
+
dataset_id=dataset_id,
|
|
973
|
+
image_ids=image_ids,
|
|
974
|
+
skip_geometry=skip_geometry,
|
|
975
|
+
)
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
{% if __webpy_script__ %}
|
|
71
71
|
<script src="https://cdn.jsdelivr.net/pyodide/{{{pyodide_version}}}/full/pyodide.js"></script>
|
|
72
72
|
{% endif %}
|
|
73
|
+
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2.0.4/dist/socket.io.js"></script>
|
|
73
74
|
<script
|
|
74
75
|
src="https://cdn.jsdelivr.net/gh/supervisely/js-bundle@{{{js_bundle_version}}}/sly-app-widgets-{{{js_bundle_version}}}.bundle.js"></script>
|
|
75
76
|
<script type="module"
|
|
@@ -257,4 +258,4 @@ if state.get("app_initializing", False) == True:
|
|
|
257
258
|
{% endif %}
|
|
258
259
|
</body>
|
|
259
260
|
|
|
260
|
-
</html>
|
|
261
|
+
</html>
|
|
@@ -14,7 +14,7 @@ from supervisely.app.widgets_context import JinjaWidgets
|
|
|
14
14
|
js_bundle_version = "2.1.99"
|
|
15
15
|
|
|
16
16
|
# https://github.com/supervisely-ecosystem/supervisely-app-frontend-js
|
|
17
|
-
js_frontend_version = "v0.0.
|
|
17
|
+
js_frontend_version = "v0.0.56"
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
pyodide_version = "v0.25.0"
|
|
@@ -50,7 +50,7 @@ supervisely/api/video_annotation_tool_api.py,sha256=3A9-U8WJzrTShP_n9T8U01M9FzGY
|
|
|
50
50
|
supervisely/api/workspace_api.py,sha256=5KAxpI9DKBmgF_pyQaXHpGT30HZ9wRtR6DP3FoYFZtY,9228
|
|
51
51
|
supervisely/api/entity_annotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
52
|
supervisely/api/entity_annotation/entity_annotation_api.py,sha256=K79KdDyepQv4FiNQHBj9V4-zLIemxK9WG1ig1bfBKb8,3083
|
|
53
|
-
supervisely/api/entity_annotation/figure_api.py,sha256=
|
|
53
|
+
supervisely/api/entity_annotation/figure_api.py,sha256=rmsE3L_JfqN94sLN637pQ0syiBAXPd8RyAwhl41j1xs,35318
|
|
54
54
|
supervisely/api/entity_annotation/object_api.py,sha256=gbcNvN_KY6G80Me8fHKQgryc2Co7VU_kfFd1GYILZ4E,8875
|
|
55
55
|
supervisely/api/entity_annotation/tag_api.py,sha256=M-28m9h8R4k9Eqo6P1S0UH8_D5kqCwAvQLYY6_Yz4oM,11161
|
|
56
56
|
supervisely/api/pointcloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -90,12 +90,12 @@ supervisely/app/development/sly-net.sh,sha256=-EVburj4NtS7Dw4OiwXXolYu9SXvui83F-
|
|
|
90
90
|
supervisely/app/fastapi/__init__.py,sha256=kNhkaGuBKn9-GNnPOmikIHqhjL-j66xmZaBbjCmXfAo,460
|
|
91
91
|
supervisely/app/fastapi/custom_static_files.py,sha256=5todaVIvUG9sAt6vu1IujJn8N7zTmFhVUfeCVbuXbvc,3391
|
|
92
92
|
supervisely/app/fastapi/dialog_window.html,sha256=ffaAxjK0TQRa7RrY5oA4uE6RzFuS0VnRG1pfoIzTqVM,1183
|
|
93
|
-
supervisely/app/fastapi/index.html,sha256=
|
|
93
|
+
supervisely/app/fastapi/index.html,sha256=ympsbjKHauNbCqDNAb-hjFM6UnOMRJf2VYEkSQFYpPk,8084
|
|
94
94
|
supervisely/app/fastapi/no_html_main.html,sha256=NhQP7noyORBx72lFh1CQKgBRupkWjiq6Gaw-9Hkvg7c,37
|
|
95
95
|
supervisely/app/fastapi/offline.py,sha256=CwMMkJ1frD6wiZS-SEoNDtQ1UJcJe1Ob6ohE3r4CQL8,7414
|
|
96
96
|
supervisely/app/fastapi/request.py,sha256=NU7rKmxJ1pfkDZ7_yHckRcRAueJRQIqCor11UO2OHr8,766
|
|
97
97
|
supervisely/app/fastapi/subapp.py,sha256=5lMfFLYBfHzE1OmITHsogB9hScyTJFjGV45AKY67Hkg,45647
|
|
98
|
-
supervisely/app/fastapi/templating.py,sha256=
|
|
98
|
+
supervisely/app/fastapi/templating.py,sha256=pcghBW2OWVrNtplZuYa-mx04ektLiSvnBg-mhmyCoJc,2929
|
|
99
99
|
supervisely/app/fastapi/utils.py,sha256=t_UquzlFrdkKtAJmH6eJ279pE8Aa3BaIu4XjX-SEaIE,946
|
|
100
100
|
supervisely/app/fastapi/websocket.py,sha256=TlRSPOAhRItTv1HGvdukK1ZvhRjMUxRa-lJlsRR9rJw,1308
|
|
101
101
|
supervisely/app/v1/__init__.py,sha256=OdU0PYv6hLwahYoyaLFO8m3cbJSchvPbqxuG1N3T734,848
|
|
@@ -1083,9 +1083,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
1083
1083
|
supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
|
|
1084
1084
|
supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
|
|
1085
1085
|
supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
|
|
1086
|
-
supervisely-6.73.
|
|
1087
|
-
supervisely-6.73.
|
|
1088
|
-
supervisely-6.73.
|
|
1089
|
-
supervisely-6.73.
|
|
1090
|
-
supervisely-6.73.
|
|
1091
|
-
supervisely-6.73.
|
|
1086
|
+
supervisely-6.73.350.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
1087
|
+
supervisely-6.73.350.dist-info/METADATA,sha256=2hZYrEUmL3RyDgh_rG9RU5RdHEfNB7aRGMhQysvHAk4,33596
|
|
1088
|
+
supervisely-6.73.350.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
|
1089
|
+
supervisely-6.73.350.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
|
|
1090
|
+
supervisely-6.73.350.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
|
|
1091
|
+
supervisely-6.73.350.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|