datamint 2.3.0__py3-none-any.whl → 2.3.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/client.py CHANGED
@@ -1,6 +1,9 @@
1
1
  from typing import Optional
2
2
  from .base_api import ApiConfig
3
- from .endpoints import ProjectsApi, ResourcesApi, AnnotationsApi, ChannelsApi, UsersApi, DatasetsInfoApi, ModelsApi
3
+ from .endpoints import (ProjectsApi, ResourcesApi, AnnotationsApi,
4
+ ChannelsApi, UsersApi, DatasetsInfoApi, ModelsApi,
5
+ AnnotationSetsApi
6
+ )
4
7
  import datamint.configs
5
8
  from datamint.exceptions import DatamintException
6
9
 
@@ -17,7 +20,8 @@ class Api:
17
20
  'channels': ChannelsApi,
18
21
  'users': UsersApi,
19
22
  'datasets': DatasetsInfoApi,
20
- 'models': ModelsApi
23
+ 'models': ModelsApi,
24
+ 'annotationsets': AnnotationSetsApi,
21
25
  }
22
26
 
23
27
  def __init__(self,
@@ -97,3 +101,7 @@ class Api:
97
101
  @property
98
102
  def models(self) -> ModelsApi:
99
103
  return self._get_endpoint('models')
104
+
105
+ @property
106
+ def annotationsets(self) -> AnnotationSetsApi:
107
+ return self._get_endpoint('annotationsets')
@@ -7,6 +7,7 @@ from .resources_api import ResourcesApi
7
7
  from .users_api import UsersApi
8
8
  from .datasetsinfo_api import DatasetsInfoApi
9
9
  from .models_api import ModelsApi
10
+ from .annotationsets_api import AnnotationSetsApi
10
11
 
11
12
  __all__ = [
12
13
  'AnnotationsApi',
@@ -16,4 +17,5 @@ __all__ = [
16
17
  'UsersApi',
17
18
  'DatasetsInfoApi',
18
19
  'ModelsApi',
20
+ 'AnnotationSetsApi',
19
21
  ]
@@ -6,6 +6,7 @@ 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
9
10
  from datamint.apihandler.dto.annotation_dto import AnnotationType, CreateAnnotationDto, LineGeometry, BoxGeometry, CoordinateSystem, Geometry
10
11
  import numpy as np
11
12
  import os
@@ -997,3 +998,33 @@ class AnnotationsApi(CreatableEntityApi[Annotation], DeletableEntityApi[Annotati
997
998
  ) -> None:
998
999
  """Alias for :py:meth:`download_multiple_files`"""
999
1000
  return self.download_multiple_files(annotations, save_paths)
1001
+
1002
+ def patch(self,
1003
+ annotation: str | Annotation,
1004
+ identifier: str) -> None:
1005
+ """
1006
+ Update the project assignment for an annotation.
1007
+
1008
+ Args:
1009
+ annotation: The annotation unique id or Annotation instance.
1010
+ identifier: The new identifier/label for the annotation.
1011
+
1012
+ Raises:
1013
+ DatamintException: If the update fails.
1014
+ """
1015
+ annotation_id = self._entid(annotation)
1016
+
1017
+ payload = {'identifier': identifier}
1018
+ # remove None values
1019
+ payload = {k: v for k, v in payload.items() if v is not None}
1020
+ if len(payload) == 0:
1021
+ _LOGGER.info("No fields to update for annotation patch.")
1022
+ return
1023
+
1024
+ resp = self._make_request('PATCH',
1025
+ f'{self.endpoint_base}/{annotation_id}',
1026
+ json=payload)
1027
+
1028
+ respdata = resp.json()
1029
+ if isinstance(respdata, dict) and 'error' in respdata:
1030
+ raise DatamintException(respdata['error'])
@@ -0,0 +1,11 @@
1
+ from datamint.api.base_api import BaseApi
2
+ import logging
3
+
4
+ _LOGGER = logging.getLogger(__name__)
5
+
6
+
7
+ class AnnotationSetsApi(BaseApi):
8
+ def get_segmentation_group(self, annotation_set_id: str) -> dict:
9
+ """Get the segmentation group for a given annotation set ID."""
10
+ endpoint = f"/annotationsets/{annotation_set_id}/segmentation-group"
11
+ return self._make_request("GET", endpoint).json()
@@ -11,7 +11,6 @@ from torch.utils.data import DataLoader
11
11
  import torch
12
12
  from torch import Tensor
13
13
  from datamint.exceptions import DatamintException
14
- from medimgkit.dicom_utils import is_dicom
15
14
  from medimgkit.readers import read_array_normalized
16
15
  from medimgkit.format_detection import guess_extension, guess_typez
17
16
  from medimgkit.nifti_utils import NIFTI_MIMES, get_nifti_shape
@@ -306,6 +305,15 @@ class DatamintBaseDataset:
306
305
  """Setup label sets and mappings."""
307
306
  self.frame_lsets, self.frame_lcodes = self._get_labels_set(framed=True)
308
307
  self.image_lsets, self.image_lcodes = self._get_labels_set(framed=False)
308
+ worklist_id = self.get_info()['worklist_id']
309
+ groups: dict[str, dict] = self.api.annotationsets.get_segmentation_group(worklist_id)['groups']
310
+ # order by 'index' key
311
+ max_index = max([g['index'] for g in groups.values()])
312
+ self.seglabel_list : list[str] = ['UNKNOWN'] * max_index # 1-based
313
+ for segname, g in groups.items():
314
+ self.seglabel_list[g['index'] - 1] = segname
315
+
316
+ self.seglabel2code = {label: idx + 1 for idx, label in enumerate(self.seglabel_list)}
309
317
 
310
318
  def _filter_items(self, images_metainfo: list[dict]) -> list[dict]:
311
319
  """Filter items that have annotations."""
@@ -357,9 +365,7 @@ class DatamintBaseDataset:
357
365
  @property
358
366
  def segmentation_labels_set(self) -> list[str]:
359
367
  """Returns the set of segmentation labels in the dataset."""
360
- a = set(self.frame_lsets['segmentation'])
361
- b = set(self.image_lsets['segmentation'])
362
- return list(a.union(b))
368
+ return self.seglabel_list
363
369
 
364
370
  def _get_annotations_internal(
365
371
  self,
@@ -463,8 +469,8 @@ class DatamintBaseDataset:
463
469
  label_anns = self.get_annotations(i, type='label', scope=scope)
464
470
  multilabel_set.update(ann.name for ann in label_anns)
465
471
 
466
- seg_anns = self.get_annotations(i, type='segmentation', scope=scope)
467
- segmentation_labels.update(ann.name for ann in seg_anns)
472
+ # seg_anns = self.get_annotations(i, type='segmentation', scope=scope)
473
+ # segmentation_labels.update(ann.name for ann in seg_anns)
468
474
 
469
475
  cat_anns = self.get_annotations(i, type='category', scope=scope)
470
476
  multiclass_set.update((ann.name, ann.value) for ann in cat_anns)
@@ -472,17 +478,17 @@ class DatamintBaseDataset:
472
478
  # Sort and create mappings
473
479
  multilabel_list = sorted(multilabel_set)
474
480
  multiclass_list = sorted(multiclass_set)
475
- segmentation_list = sorted(segmentation_labels)
481
+ # segmentation_list = sorted(segmentation_labels)
476
482
 
477
483
  sets = {
478
484
  'multilabel': multilabel_list,
479
- 'segmentation': segmentation_list,
485
+ # 'segmentation': segmentation_list,
480
486
  'multiclass': multiclass_list
481
487
  }
482
488
 
483
489
  codes_map = {
484
490
  'multilabel': {label: idx for idx, label in enumerate(multilabel_list)},
485
- 'segmentation': {label: idx + 1 for idx, label in enumerate(segmentation_list)},
491
+ # 'segmentation': {label: idx + 1 for idx, label in enumerate(segmentation_list)},
486
492
  'multiclass': {label: idx for idx, label in enumerate(multiclass_list)}
487
493
  }
488
494
 
@@ -191,7 +191,7 @@ class DatamintDataset(DatamintBaseDataset):
191
191
  author_labels = seg_labels[author]
192
192
 
193
193
  if frame_index is not None and ann.scope == 'frame':
194
- seg_code = self.frame_lcodes['segmentation'][ann.name]
194
+ seg_code = self.seglabel2code[ann.name]
195
195
  if author_segs[frame_index] is None:
196
196
  author_segs[frame_index] = []
197
197
  author_labels[frame_index] = []
@@ -199,7 +199,7 @@ class DatamintDataset(DatamintBaseDataset):
199
199
  author_segs[frame_index].append(s)
200
200
  author_labels[frame_index].append(seg_code)
201
201
  elif frame_index is None and ann.scope == 'image':
202
- seg_code = self.image_lcodes['segmentation'][ann.name]
202
+ seg_code = self.seglabel2code[ann.name]
203
203
  # apply to all frames
204
204
  for i in range(nframes):
205
205
  if author_segs[i] is None:
@@ -3,6 +3,7 @@
3
3
  from datetime import datetime
4
4
  import logging
5
5
  from .base_entity import BaseEntity, MISSING_FIELD
6
+ from typing import Any
6
7
 
7
8
  logger = logging.getLogger(__name__)
8
9
 
@@ -43,9 +44,10 @@ class Project(BaseEntity):
43
44
  resource_count: int
44
45
  annotated_resource_count: int
45
46
  description: str | None
46
- ai_model_id: str | None
47
47
  viewable_ai_segs: list | None
48
48
  editable_ai_segs: list | None
49
+ registered_model: Any | None = MISSING_FIELD
50
+ ai_model_id: str | None = MISSING_FIELD
49
51
  closed_resources_count: int = MISSING_FIELD
50
52
  resources_to_annotate_count: int = MISSING_FIELD
51
53
  most_recent_experiment: str | None = MISSING_FIELD # ISO timestamp string
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datamint
3
- Version: 2.3.0
3
+ Version: 2.3.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,10 +1,11 @@
1
1
  datamint/__init__.py,sha256=ucsnxrYClh6pdy7psRJXWam_9rjAQB4NXzvy7xLovmo,824
2
2
  datamint/api/__init__.py,sha256=7QYkmDBXbKh8-zchV7k6Lpolaw6h-IK6ezfXROIWh2A,43
3
3
  datamint/api/base_api.py,sha256=Iu9oJEZ8YlIF5xcbH_M0Lkb7t9ZDNFLzjJp9bPDHW1c,16628
4
- datamint/api/client.py,sha256=qL6kW1lUma98LieDEkhRdJAGRcsEFlaBSg2oQ3ZePYY,3466
4
+ datamint/api/client.py,sha256=WfcCpvH3tl0nQ9SgRdQG0qy8A7tD_2dytRxQUln3G9Y,3724
5
5
  datamint/api/dto/__init__.py,sha256=KOSNl1axDDE5eBt68MmsgkyE0Ds_1DDzWUg73iyoWvc,281
6
- datamint/api/endpoints/__init__.py,sha256=uN2EYxSL6T5O5poVmQs8CQpyy3_MZzHfNyniORcvKUc,454
7
- datamint/api/endpoints/annotations_api.py,sha256=Uyx-gnh5f-Di7MU_doQheYlSOkqjf7hlFnmaruvWQN4,47098
6
+ datamint/api/endpoints/__init__.py,sha256=wi4liAb5-wOohwyzKUD6TxHGeZmUPaZerFUGa2IUju4,529
7
+ datamint/api/endpoints/annotations_api.py,sha256=jhaWkLd01zKw-lVQYhBX288o9Ew2lQ-jmRP-0fz2fx0,48185
8
+ datamint/api/endpoints/annotationsets_api.py,sha256=NIsPIjGGptiUBxHft-EhOMRG-DsQAthheVqd7ph0id4,409
8
9
  datamint/api/endpoints/channels_api.py,sha256=oQqxSw9DJzAqtVQI7-tc1llTdnsm-URx8jwtXNXnhio,867
9
10
  datamint/api/endpoints/datasetsinfo_api.py,sha256=WdzrUzK63w9gvAP6U--P65FbD-3X-jm9TPCcYnRNjas,597
10
11
  datamint/api/endpoints/models_api.py,sha256=tbVuajc-mCsIp5AKSCoq3uQRDWgKnJaIA6tf_ck8-XY,1502
@@ -25,14 +26,14 @@ datamint/client_cmd_tools/datamint_upload.py,sha256=rZEqBRZZDBFSlwMvIg_DbipqgBtQ
25
26
  datamint/configs.py,sha256=Bdp6NydYwyCJ2dk19_gf_o3M2ZyQOmMHpLi8wEWNHUk,1426
26
27
  datamint/dataset/__init__.py,sha256=4PlUKSvVhdfQvvuq8jQXrkdqnot-iTTizM3aM1vgSwg,47
27
28
  datamint/dataset/annotation.py,sha256=qN1IMjdfLD2ceQ6va3l76jOXA8Vb_c-eBk1oWQu6hW0,7994
28
- datamint/dataset/base_dataset.py,sha256=Za41Qf76nm3GmY7iA9mba_FGzzwF3gxqAwu4eY0_5b4,49479
29
- datamint/dataset/dataset.py,sha256=Oj_Xr6MaCdO2Nq16fFE345qoKMWaTzKk6M1G6ajSXMo,28959
29
+ datamint/dataset/base_dataset.py,sha256=pJXU_nY9_D67E7G3cjnVnwdzjNNJgOhMt-i687oHgtw,49869
30
+ datamint/dataset/dataset.py,sha256=c0887PcI6fEWG3FjM3gz_EYb9maH8v4ormZhm7vf4gE,28929
30
31
  datamint/entities/__init__.py,sha256=tbHE7rZb0R9Hm-Dc8VWEq3PlRl7BYOzffumrV0ZdsMs,444
31
32
  datamint/entities/annotation.py,sha256=ochAEh_JqxAe_FyYTNUfPT47KiIAG7CkBTim52bu7M8,6636
32
33
  datamint/entities/base_entity.py,sha256=DniakCgJ-gV7Hz8VKQA_dRYTp4DU5rcjLBVOuD1aZuA,1902
33
34
  datamint/entities/channel.py,sha256=9fl22eSx_ng98NosfQGs18cdaRdbeC3wXL61KhSg4Zo,1601
34
35
  datamint/entities/datasetinfo.py,sha256=O73Aq0tLflQomFzseful8a_cXqKdO9w2yP0p3zBcA-s,489
35
- datamint/entities/project.py,sha256=cK03qfVBVUTFJF0IZQCGfjX-ivzDytySakKoVbjfnz0,2588
36
+ datamint/entities/project.py,sha256=FNweb1Q0ZQkWfbyijoV-UyqUXthzookdcyO-ophAl0U,2676
36
37
  datamint/entities/resource.py,sha256=7YCVihswd-bH-2AH4aMPIddt5ejwRqRFQAszI_sTWaU,4882
37
38
  datamint/entities/user.py,sha256=MREHDOsV9NOBEbXqiQ2ww6DmetN07CELId-ZQVpZCb8,620
38
39
  datamint/examples/__init__.py,sha256=zcYnd5nLVme9GCTPYH-1JpGo8xXK2WEYvhzcy_2alZc,39
@@ -45,7 +46,7 @@ datamint/logging.yaml,sha256=tOMxtc2UmwlIMTK6ljtnBwTco1PNrPeq3mx2iMuSbiw,482
45
46
  datamint/utils/logging_utils.py,sha256=9pRoaPrWu2jOdDCiAoUsjEdP5ZwaealWL3hjUqFvx9g,4022
46
47
  datamint/utils/torchmetrics.py,sha256=lwU0nOtsSWfebyp7dvjlAggaqXtj5ohSEUXOg3L0hJE,2837
47
48
  datamint/utils/visualization.py,sha256=yaUVAOHar59VrGUjpAWv5eVvQSfztFG0eP9p5Vt3l-M,4470
48
- datamint-2.3.0.dist-info/METADATA,sha256=lV7qLnGCc1NA5yShMM-oTLkoy5FAKWwGd9rNgeu6K_M,4203
49
- datamint-2.3.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
50
- datamint-2.3.0.dist-info/entry_points.txt,sha256=mn5H6jPjO-rY0W0CAZ6Z_KKWhMLvyVaSpoqk77jlTI4,145
51
- datamint-2.3.0.dist-info/RECORD,,
49
+ datamint-2.3.2.dist-info/METADATA,sha256=wybrUAOXVw_v1HzHAamP9uGMO7mAemu87lmDf7-0mbE,4203
50
+ datamint-2.3.2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
51
+ datamint-2.3.2.dist-info/entry_points.txt,sha256=mn5H6jPjO-rY0W0CAZ6Z_KKWhMLvyVaSpoqk77jlTI4,145
52
+ datamint-2.3.2.dist-info/RECORD,,