datamint 2.4.0__py3-none-any.whl → 2.4.2__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 datamint might be problematic. Click here for more details.

datamint/api/__init__.py CHANGED
@@ -1,3 +0,0 @@
1
- from .client import Api
2
-
3
- __all__ = ['Api']
@@ -6,7 +6,6 @@ from ..entity_base_api import ApiConfig, CreatableEntityApi, DeletableEntityApi
6
6
  from .models_api import ModelsApi
7
7
  from datamint.entities.annotation import Annotation
8
8
  from datamint.entities.resource import Resource
9
- from datamint.entities.project import Project
10
9
  from datamint.api.dto import AnnotationType, CreateAnnotationDto, LineGeometry, BoxGeometry, CoordinateSystem, Geometry
11
10
  import numpy as np
12
11
  import os
@@ -2,9 +2,9 @@ from typing import Any, Optional, Sequence, TypeAlias, Literal, IO
2
2
  from ..base_api import ApiConfig, BaseApi
3
3
  from ..entity_base_api import CreatableEntityApi, DeletableEntityApi
4
4
  from datamint.entities.resource import Resource
5
- from datamint.entities.project import Project
6
5
  from datamint.entities.annotation import Annotation
7
6
  from datamint.exceptions import DatamintException, ResourceNotFoundError
7
+ from datamint.api.dto import AnnotationType
8
8
  import httpx
9
9
  from datetime import date
10
10
  import json
@@ -25,6 +25,7 @@ import nest_asyncio # For running asyncio in jupyter notebooks
25
25
  from PIL import Image
26
26
  import io
27
27
  from datamint.types import ImagingData
28
+ from collections import defaultdict
28
29
 
29
30
 
30
31
  _LOGGER = logging.getLogger(__name__)
@@ -146,7 +147,8 @@ class ResourcesApi(CreatableEntityApi[Resource], DeletableEntityApi[Resource]):
146
147
 
147
148
  return super().get_list(limit=limit, params=payload)
148
149
 
149
- def get_annotations(self, resource: str | Resource) -> Sequence[Annotation]:
150
+ def get_annotations(self, resource: str | Resource,
151
+ annotation_type: AnnotationType | str | None = None) -> Sequence[Annotation]:
150
152
  """Get annotations for a specific resource.
151
153
 
152
154
  Args:
@@ -155,7 +157,9 @@ class ResourcesApi(CreatableEntityApi[Resource], DeletableEntityApi[Resource]):
155
157
  Returns:
156
158
  A sequence of Annotation objects associated with the specified resource.
157
159
  """
158
- return self.annotations_api.get_list(resource=resource)
160
+ return self.annotations_api.get_list(resource=resource,
161
+ load_ai_segmentations=True,
162
+ annotation_type=annotation_type)
159
163
 
160
164
  @staticmethod
161
165
  def __process_files_parameter(file_path: str | Sequence[str | IO | pydicom.Dataset]
@@ -279,7 +283,6 @@ class ResourcesApi(CreatableEntityApi[Resource], DeletableEntityApi[Resource]):
279
283
  _LOGGER.warning(msg)
280
284
  _USER_LOGGER.warning(msg)
281
285
 
282
-
283
286
  mimetype = standardize_mimetype(mimetype)
284
287
 
285
288
  if is_a_dicom_file == True or is_dicom(file_path):
@@ -440,12 +443,12 @@ class ResourcesApi(CreatableEntityApi[Resource], DeletableEntityApi[Resource]):
440
443
 
441
444
  try:
442
445
  tasks = [__upload_single_resource(f, segfiles, metadata_file)
443
- for f, segfiles, metadata_file in zip(files_path, segmentation_files, metadata_files)]
446
+ for f, segfiles, metadata_file in zip(files_path, segmentation_files, metadata_files)]
444
447
  except ValueError:
445
448
  msg = f"Error preparing upload tasks. Try `assemble_dicom=False`."
446
449
  _LOGGER.error(msg)
447
450
  _USER_LOGGER.error(msg)
448
- raise
451
+ raise
449
452
  return await asyncio.gather(*tasks, return_exceptions=on_error == 'skip')
450
453
 
451
454
  def upload_resources(self,
@@ -996,22 +999,28 @@ class ResourcesApi(CreatableEntityApi[Resource], DeletableEntityApi[Resource]):
996
999
  raise
997
1000
 
998
1001
  def set_tags(self,
999
- resource: str | Resource,
1002
+ resource: str | Resource | Sequence[str | Resource],
1000
1003
  tags: Sequence[str],
1001
1004
  ):
1002
1005
  """
1003
1006
  Set tags for a resource, IMPORTANT: This replaces all existing tags.
1004
1007
  Args:
1005
- resource: The resource unique id or Resource object.
1008
+ resource: The resource object or a list of resources.
1006
1009
  tags: The tags to set.
1007
1010
  """
1008
1011
  data = {'tags': tags}
1009
- resource_id = self._entid(resource)
1010
-
1011
- response = self._make_entity_request('PUT',
1012
- resource_id,
1013
- add_path='tags',
1014
- json=data)
1012
+ if isinstance(resource, Sequence):
1013
+ resource_ids = [self._entid(res) for res in resource]
1014
+ response = self._make_request('PUT',
1015
+ f'{self.endpoint_base}/tags',
1016
+ json={'resource_ids': resource_ids,
1017
+ 'tags': tags})
1018
+ else:
1019
+ resource_id = self._entid(resource)
1020
+ response = self._make_entity_request('PUT',
1021
+ resource_id,
1022
+ add_path='tags',
1023
+ json=data)
1015
1024
  return response
1016
1025
 
1017
1026
  # def get_projects(self, resource: Resource) -> Sequence[Project]:
@@ -1029,7 +1038,7 @@ class ResourcesApi(CreatableEntityApi[Resource], DeletableEntityApi[Resource]):
1029
1038
  # return [proj for proj in self.projects_api.get_all() if proj.id in proj_ids]
1030
1039
 
1031
1040
  def add_tags(self,
1032
- resource: str | Resource,
1041
+ resource: str | Resource | Sequence[str | Resource],
1033
1042
  tags: Sequence[str],
1034
1043
  ):
1035
1044
  """
@@ -1040,8 +1049,26 @@ class ResourcesApi(CreatableEntityApi[Resource], DeletableEntityApi[Resource]):
1040
1049
  """
1041
1050
  if isinstance(resource, str):
1042
1051
  resource = self.get_by_id(resource)
1052
+ elif isinstance(resource, Sequence):
1053
+ # Transform every str to Resource first.
1054
+ resources = [self.get_by_id(res) if isinstance(res, str) else res for res in resource]
1055
+
1056
+ # group resource having the exact same tags to minimize requests
1057
+ tag_map: dict[tuple, list[Resource]] = defaultdict(list)
1058
+ for res in resources:
1059
+ old_tags = res.tags if res.tags is not None else []
1060
+ # key = tuple(sorted(old_tags))
1061
+ key = tuple(old_tags) # keep order, assuming order matters for tags
1062
+ tag_map[key].append(res)
1063
+
1064
+ # finally, set tags for each group
1065
+ for old_tags_tuple, res_group in tag_map.items():
1066
+ old_tags = list(old_tags_tuple)
1067
+ self.set_tags(res_group, old_tags + list(tags))
1068
+ return
1069
+
1043
1070
  old_tags = resource.tags if resource.tags is not None else []
1044
- return self.set_tags(resource, old_tags + list(tags))
1071
+ self.set_tags(resource, old_tags + list(tags))
1045
1072
 
1046
1073
  def bulk_delete(self, entities: Sequence[str | Resource]) -> None:
1047
1074
  """Delete multiple entities. Faster than deleting them one by one.
@@ -176,11 +176,7 @@ class Resource(BaseEntity):
176
176
  ) -> Sequence['Annotation']:
177
177
  """Get annotations associated with this resource."""
178
178
 
179
- annotations = self._api.get_annotations(self)
180
-
181
- if annotation_type:
182
- annotation_type = AnnotationType(annotation_type)
183
- annotations = [a for a in annotations if a.annotation_type == annotation_type]
179
+ annotations = self._api.get_annotations(self, annotation_type=annotation_type)
184
180
  return annotations
185
181
 
186
182
  # def get_projects(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datamint
3
- Version: 2.4.0
3
+ Version: 2.4.2
4
4
  Summary: A library for interacting with the Datamint API, designed for efficient data management, processing and Deep Learning workflows.
5
5
  Requires-Python: >=3.10
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,16 +1,16 @@
1
1
  datamint/__init__.py,sha256=ucsnxrYClh6pdy7psRJXWam_9rjAQB4NXzvy7xLovmo,824
2
- datamint/api/__init__.py,sha256=7QYkmDBXbKh8-zchV7k6Lpolaw6h-IK6ezfXROIWh2A,43
2
+ datamint/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  datamint/api/base_api.py,sha256=q-TQKFbupUPCaOTihoFEljxCyTF76ojsDoGkhtIJRPc,20194
4
4
  datamint/api/client.py,sha256=x-hkoDoKBWqwVCLbFZjHEWEwfqxo8bwVUSIWB4aebYQ,4018
5
5
  datamint/api/dto/__init__.py,sha256=fUi901Zs-q5XHyWwZ4dMi2fEO8-CUEVEdYbpd17lahc,416
6
6
  datamint/api/endpoints/__init__.py,sha256=wi4liAb5-wOohwyzKUD6TxHGeZmUPaZerFUGa2IUju4,529
7
- datamint/api/endpoints/annotations_api.py,sha256=B21oGgNXO7xoir3ynNvhnbo1JyRvWZ9sbsc7VVjghhM,49713
7
+ datamint/api/endpoints/annotations_api.py,sha256=tkYGljljA1mdnLmmtbw6jP1qDowDygvHC1oIzJ9TLoM,49667
8
8
  datamint/api/endpoints/annotationsets_api.py,sha256=NIsPIjGGptiUBxHft-EhOMRG-DsQAthheVqd7ph0id4,409
9
9
  datamint/api/endpoints/channels_api.py,sha256=oQqxSw9DJzAqtVQI7-tc1llTdnsm-URx8jwtXNXnhio,867
10
10
  datamint/api/endpoints/datasetsinfo_api.py,sha256=WdzrUzK63w9gvAP6U--P65FbD-3X-jm9TPCcYnRNjas,597
11
11
  datamint/api/endpoints/models_api.py,sha256=tbVuajc-mCsIp5AKSCoq3uQRDWgKnJaIA6tf_ck8-XY,1502
12
12
  datamint/api/endpoints/projects_api.py,sha256=Pfr3fEiMw_aRzoGtcVXHJQ68leVoPAghw23L4ZIglno,8237
13
- datamint/api/endpoints/resources_api.py,sha256=ZsGy4xTdLHLkM2z8VyRRLEjB0Rv3kTZFQceYkFYpk7A,50601
13
+ datamint/api/endpoints/resources_api.py,sha256=PY3QMF9yPdO07YDMWpGTC7U3GC4H7R_4KfnUSAKuOXg,52177
14
14
  datamint/api/endpoints/users_api.py,sha256=pnkuTZ1B9Y0FtwwvXO8J64e02RSkRxnBmTl9UGSuC5I,1186
15
15
  datamint/api/entity_base_api.py,sha256=-8SIt4M8P9G2b8SQznuWpFuFE8zEQjQxkRkw0s_w0Y4,11692
16
16
  datamint/apihandler/annotation_api_handler.py,sha256=W3vV4z3BqX1OQe1r7zr8dI-IVu4zUDxED4QttdiWV-E,57098
@@ -35,7 +35,7 @@ datamint/entities/cache_manager.py,sha256=ZN5_HeyM6c0ocWFsJuJEF4CkuOHr6RPErwhZNY
35
35
  datamint/entities/channel.py,sha256=9fl22eSx_ng98NosfQGs18cdaRdbeC3wXL61KhSg4Zo,1601
36
36
  datamint/entities/datasetinfo.py,sha256=yeGy5CVxqc7h0SFBJROr0UObeIMkOVZKwrOBsZ-iCEg,4151
37
37
  datamint/entities/project.py,sha256=QQXBOe6FzupPrCunBcqOlY6d3uqxvnYvGeCq8hZy_U8,4192
38
- datamint/entities/resource.py,sha256=Ai36-dJ9PhrRYho8QLRnySfsAPWPW8QpKMiVra_jCgA,9316
38
+ datamint/entities/resource.py,sha256=z7W49TyiHXHYLAsijIcPYQfhJcsQDgBzWNAMckAsYFE,9167
39
39
  datamint/entities/user.py,sha256=MREHDOsV9NOBEbXqiQ2ww6DmetN07CELId-ZQVpZCb8,620
40
40
  datamint/examples/__init__.py,sha256=zcYnd5nLVme9GCTPYH-1JpGo8xXK2WEYvhzcy_2alZc,39
41
41
  datamint/examples/example_projects.py,sha256=sU-Gxy7PPqA0WUfN-ZmXV-0YnwrnzpJ79lMXTJp2DzU,2804
@@ -61,7 +61,7 @@ datamint/types.py,sha256=2OaY5QJvQIJKxyMNJYzxBksKCa9ZS2gb_ayJrByvu2Y,410
61
61
  datamint/utils/logging_utils.py,sha256=9pRoaPrWu2jOdDCiAoUsjEdP5ZwaealWL3hjUqFvx9g,4022
62
62
  datamint/utils/torchmetrics.py,sha256=lwU0nOtsSWfebyp7dvjlAggaqXtj5ohSEUXOg3L0hJE,2837
63
63
  datamint/utils/visualization.py,sha256=yaUVAOHar59VrGUjpAWv5eVvQSfztFG0eP9p5Vt3l-M,4470
64
- datamint-2.4.0.dist-info/METADATA,sha256=g4WkKWDq3mBETvQibcoISGXTtQCRdebfrw4leyurg3E,8974
65
- datamint-2.4.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
66
- datamint-2.4.0.dist-info/entry_points.txt,sha256=wTr9DXteCfAFqLUstN1Qx_SqC_rFLrAUIcDx9q1eXZw,845
67
- datamint-2.4.0.dist-info/RECORD,,
64
+ datamint-2.4.2.dist-info/METADATA,sha256=GUVaw9czq5utZnZErSe9ohdXB7LROheAwGYkacvX6AY,8974
65
+ datamint-2.4.2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
66
+ datamint-2.4.2.dist-info/entry_points.txt,sha256=wTr9DXteCfAFqLUstN1Qx_SqC_rFLrAUIcDx9q1eXZw,845
67
+ datamint-2.4.2.dist-info/RECORD,,