datamint 1.7.6__py3-none-any.whl → 1.9.0__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/apihandler/base_api_handler.py +2 -3
- datamint/apihandler/root_api_handler.py +16 -10
- datamint/client_cmd_tools/datamint_upload.py +66 -15
- {datamint-1.7.6.dist-info → datamint-1.9.0.dist-info}/METADATA +2 -2
- {datamint-1.7.6.dist-info → datamint-1.9.0.dist-info}/RECORD +7 -7
- {datamint-1.7.6.dist-info → datamint-1.9.0.dist-info}/WHEEL +0 -0
- {datamint-1.7.6.dist-info → datamint-1.9.0.dist-info}/entry_points.txt +0 -0
|
@@ -119,9 +119,6 @@ class BaseAPIHandler:
|
|
|
119
119
|
if method != 'GET':
|
|
120
120
|
curl_command.extend(['-X', method])
|
|
121
121
|
|
|
122
|
-
# Add URL
|
|
123
|
-
curl_command.append(f"'{url}'")
|
|
124
|
-
|
|
125
122
|
# Add headers
|
|
126
123
|
for key, value in headers.items():
|
|
127
124
|
if key.lower() == 'apikey':
|
|
@@ -132,6 +129,8 @@ class BaseAPIHandler:
|
|
|
132
129
|
if params:
|
|
133
130
|
param_str = '&'.join([f"{k}={v}" for k, v in params.items()])
|
|
134
131
|
url = f"{url}?{param_str}"
|
|
132
|
+
# Add URL
|
|
133
|
+
curl_command.append(f"'{url}'")
|
|
135
134
|
|
|
136
135
|
# Add data
|
|
137
136
|
if data:
|
|
@@ -8,7 +8,7 @@ import asyncio
|
|
|
8
8
|
import aiohttp
|
|
9
9
|
from medimgkit.dicom_utils import anonymize_dicom, to_bytesio, is_dicom, is_dicom_report
|
|
10
10
|
from medimgkit import dicom_utils, standardize_mimetype
|
|
11
|
-
from medimgkit.io_utils import is_io_object
|
|
11
|
+
from medimgkit.io_utils import is_io_object, peek
|
|
12
12
|
from medimgkit.format_detection import guess_typez, guess_extension, DEFAULT_MIME_TYPE
|
|
13
13
|
from medimgkit.nifti_utils import DEFAULT_NIFTI_MIME, NIFTI_MIMES
|
|
14
14
|
import pydicom
|
|
@@ -103,16 +103,22 @@ class RootAPIHandler(BaseAPIHandler):
|
|
|
103
103
|
filename = os.path.basename(name)
|
|
104
104
|
_LOGGER.debug(f"File name '{filename}' mimetype: {mimetype}")
|
|
105
105
|
|
|
106
|
-
if
|
|
107
|
-
if
|
|
108
|
-
|
|
106
|
+
if is_a_dicom_file == True or is_dicom(file_path):
|
|
107
|
+
if tags is None:
|
|
108
|
+
tags = []
|
|
109
|
+
else:
|
|
110
|
+
tags = list(tags)
|
|
111
|
+
ds = pydicom.dcmread(file_path)
|
|
112
|
+
if anonymize:
|
|
109
113
|
_LOGGER.info(f"Anonymizing {file_path}")
|
|
110
114
|
ds = anonymize_dicom(ds, retain_codes=anonymize_retain_codes)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
115
|
+
lat = dicom_utils.get_dicom_laterality(ds)
|
|
116
|
+
if lat == 'L':
|
|
117
|
+
tags.append("left")
|
|
118
|
+
elif lat == 'R':
|
|
119
|
+
tags.append("right")
|
|
120
|
+
# make the dicom `ds` object a file-like object in order to avoid unnecessary disk writes
|
|
121
|
+
f = to_bytesio(ds, name)
|
|
116
122
|
else:
|
|
117
123
|
f = _open_io(file_path)
|
|
118
124
|
|
|
@@ -437,7 +443,7 @@ class RootAPIHandler(BaseAPIHandler):
|
|
|
437
443
|
if assemble_dicoms:
|
|
438
444
|
files_path, assembled = self._assemble_dicoms(files_path)
|
|
439
445
|
assemble_dicoms = assembled
|
|
440
|
-
|
|
446
|
+
|
|
441
447
|
if segmentation_files is not None:
|
|
442
448
|
if assemble_dicoms:
|
|
443
449
|
raise NotImplementedError("Segmentation files cannot be uploaded when assembling dicoms yet.")
|
|
@@ -5,7 +5,7 @@ from humanize import naturalsize
|
|
|
5
5
|
import logging
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
import sys
|
|
8
|
-
from medimgkit.dicom_utils import is_dicom
|
|
8
|
+
from medimgkit.dicom_utils import is_dicom, detect_dicomdir, parse_dicomdir_files
|
|
9
9
|
import fnmatch
|
|
10
10
|
from typing import Generator, Optional, Any
|
|
11
11
|
from collections import defaultdict
|
|
@@ -35,7 +35,7 @@ def _read_segmentation_names(segmentation_names_path: str | Path) -> dict:
|
|
|
35
35
|
if segmentation_names_path.suffix in ['.yaml', '.yml']:
|
|
36
36
|
with open(segmentation_names_path, 'r') as f:
|
|
37
37
|
metadata = yaml.safe_load(f)
|
|
38
|
-
elif segmentation_names_path.suffix in ['.csv', '.tsv']:
|
|
38
|
+
elif segmentation_names_path.suffix in ['.csv', '.tsv', '.txt']:
|
|
39
39
|
df = pd.read_csv(segmentation_names_path,
|
|
40
40
|
header=None,
|
|
41
41
|
index_col=0,
|
|
@@ -124,6 +124,22 @@ def walk_to_depth(path: str | Path,
|
|
|
124
124
|
depth: int,
|
|
125
125
|
exclude_pattern: str | None = None) -> Generator[Path, None, None]:
|
|
126
126
|
path = Path(path)
|
|
127
|
+
|
|
128
|
+
# Check for DICOMDIR first at current directory level
|
|
129
|
+
dicomdir_path = detect_dicomdir(path)
|
|
130
|
+
if dicomdir_path is not None:
|
|
131
|
+
try:
|
|
132
|
+
_USER_LOGGER.info(f"Found DICOMDIR file at {path}. Using it as authoritative source for file listing.")
|
|
133
|
+
dicom_files = parse_dicomdir_files(dicomdir_path)
|
|
134
|
+
# Yield all DICOM files from DICOMDIR and return early
|
|
135
|
+
for dicom_file in dicom_files:
|
|
136
|
+
yield dicom_file
|
|
137
|
+
return
|
|
138
|
+
except Exception as e:
|
|
139
|
+
_USER_LOGGER.warning(f"Failed to parse DICOMDIR at {path}: {e}. Falling back to directory scan.")
|
|
140
|
+
# Continue with regular directory scanning below
|
|
141
|
+
|
|
142
|
+
# Regular directory scanning
|
|
127
143
|
for child in path.iterdir():
|
|
128
144
|
if _is_system_file(child):
|
|
129
145
|
continue
|
|
@@ -386,6 +402,46 @@ def _collect_metadata_files(files_path: list[str], auto_detect_json: bool) -> tu
|
|
|
386
402
|
return metadata_files, filtered_files_path
|
|
387
403
|
|
|
388
404
|
|
|
405
|
+
def _get_files_from_path(path: str | Path,
|
|
406
|
+
recursive_depth: Optional[int] = None,
|
|
407
|
+
exclude_pattern: Optional[str] = None,
|
|
408
|
+
include_extensions: Optional[list[str]] = None,
|
|
409
|
+
exclude_extensions: Optional[list[str]] = None) -> list[str]:
|
|
410
|
+
"""
|
|
411
|
+
Get files from a path with recursive DICOMDIR detection and parsing.
|
|
412
|
+
|
|
413
|
+
Args:
|
|
414
|
+
path: Path to search for files
|
|
415
|
+
recursive_depth: Depth for recursive search (None for no recursion, -1 for unlimited)
|
|
416
|
+
exclude_pattern: Pattern to exclude directories
|
|
417
|
+
include_extensions: File extensions to include
|
|
418
|
+
exclude_extensions: File extensions to exclude
|
|
419
|
+
|
|
420
|
+
Returns:
|
|
421
|
+
List of file paths as strings
|
|
422
|
+
"""
|
|
423
|
+
path = Path(path)
|
|
424
|
+
|
|
425
|
+
if path.is_file():
|
|
426
|
+
return [str(path)]
|
|
427
|
+
|
|
428
|
+
try:
|
|
429
|
+
if recursive_depth is None:
|
|
430
|
+
recursive_depth = 0
|
|
431
|
+
elif recursive_depth < 0:
|
|
432
|
+
recursive_depth = MAX_RECURSION_LIMIT
|
|
433
|
+
else:
|
|
434
|
+
recursive_depth = min(MAX_RECURSION_LIMIT, recursive_depth)
|
|
435
|
+
|
|
436
|
+
file_paths = walk_to_depth(path, recursive_depth, exclude_pattern)
|
|
437
|
+
filtered_files = filter_files(file_paths, include_extensions, exclude_extensions)
|
|
438
|
+
return [str(f) for f in filtered_files]
|
|
439
|
+
|
|
440
|
+
except Exception as e:
|
|
441
|
+
_LOGGER.error(f'Error in recursive search: {e}')
|
|
442
|
+
raise
|
|
443
|
+
|
|
444
|
+
|
|
389
445
|
def _parse_args() -> tuple[Any, list[str], Optional[list[dict]], Optional[list[str]]]:
|
|
390
446
|
parser = argparse.ArgumentParser(
|
|
391
447
|
description='DatamintAPI command line tool for uploading DICOM files and other resources')
|
|
@@ -433,7 +489,7 @@ def _parse_args() -> tuple[Any, list[str], Optional[list[dict]], Optional[list[s
|
|
|
433
489
|
required=False,
|
|
434
490
|
help='Path to a yaml or csv file containing the segmentation names.' +
|
|
435
491
|
' If yaml, the file may contain two keys: "segmentation_names" and "class_names".'
|
|
436
|
-
' If csv, the file should contain the following columns:'
|
|
492
|
+
' If csv, the file should be in itk-snap label export format, i.e, it should contain the following columns (with no header):'
|
|
437
493
|
' index, r, g, b, ..., name')
|
|
438
494
|
parser.add_argument('--yes', action='store_true',
|
|
439
495
|
help='Automatically answer yes to all prompts')
|
|
@@ -482,18 +538,13 @@ def _parse_args() -> tuple[Any, list[str], Optional[list[dict]], Optional[list[s
|
|
|
482
538
|
if args.recursive is not None:
|
|
483
539
|
_USER_LOGGER.warning("Recursive flag ignored. Specified path is a file.")
|
|
484
540
|
else:
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
file_path = filter_files(file_path, args.include_extensions, args.exclude_extensions)
|
|
493
|
-
file_path = list(map(str, file_path)) # from Path to str
|
|
494
|
-
except Exception as e:
|
|
495
|
-
_LOGGER.error(f'Error in recursive search: {e}')
|
|
496
|
-
raise e
|
|
541
|
+
file_path = _get_files_from_path(
|
|
542
|
+
path=args.path,
|
|
543
|
+
recursive_depth=args.recursive,
|
|
544
|
+
exclude_pattern=args.exclude,
|
|
545
|
+
include_extensions=args.include_extensions,
|
|
546
|
+
exclude_extensions=args.exclude_extensions
|
|
547
|
+
)
|
|
497
548
|
|
|
498
549
|
if len(file_path) == 0:
|
|
499
550
|
raise ValueError(f"No valid file was found in {args.path}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: datamint
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9.0
|
|
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
|
|
@@ -19,7 +19,7 @@ Requires-Dist: humanize (>=4.0.0,<5.0.0)
|
|
|
19
19
|
Requires-Dist: lazy-loader (>=0.3.0)
|
|
20
20
|
Requires-Dist: lightning
|
|
21
21
|
Requires-Dist: matplotlib
|
|
22
|
-
Requires-Dist: medimgkit (>=0.
|
|
22
|
+
Requires-Dist: medimgkit (>=0.4.4)
|
|
23
23
|
Requires-Dist: nest-asyncio (>=1.0.0,<2.0.0)
|
|
24
24
|
Requires-Dist: nibabel (>=4.0.0)
|
|
25
25
|
Requires-Dist: numpy
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
datamint/__init__.py,sha256=7rKCCsaa4RBRTIfuHB708rai1xwDHLtkFNFJGKYG5D4,757
|
|
2
2
|
datamint/apihandler/annotation_api_handler.py,sha256=ZJJD_Op8eDtGcpDZOS1DRjqyDUdD3UxvtuNJK9FaPOk,57063
|
|
3
3
|
datamint/apihandler/api_handler.py,sha256=cdVSddrFCKlF_BJ81LO1aJ0OP49rssjpNEFzJ6Q7YyY,384
|
|
4
|
-
datamint/apihandler/base_api_handler.py,sha256=
|
|
4
|
+
datamint/apihandler/base_api_handler.py,sha256=GQuJS3FFjxPi-2vkJtbHeNKywoa-PWa3Qvw3NGRzxug,12206
|
|
5
5
|
datamint/apihandler/dto/annotation_dto.py,sha256=qId1RK1VO7dXrvGJ7dqJ31jBQB7Z8yy5x0tLSiMxTB4,7105
|
|
6
6
|
datamint/apihandler/exp_api_handler.py,sha256=hFUgUgBc5rL7odK7gTW3MnrvMY1pVfJUpUdzRNobMQE,6226
|
|
7
|
-
datamint/apihandler/root_api_handler.py,sha256=
|
|
7
|
+
datamint/apihandler/root_api_handler.py,sha256=_vgIjqt7jb1yUkhyMez1Tg-vs4xmExby4TqWnfQG4OI,59320
|
|
8
8
|
datamint/client_cmd_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
datamint/client_cmd_tools/datamint_config.py,sha256=md7dnWrbl10lPtXKbmD9yo6onLJsajeG8Vz0ZWH1v4M,8181
|
|
10
|
-
datamint/client_cmd_tools/datamint_upload.py,sha256=
|
|
10
|
+
datamint/client_cmd_tools/datamint_upload.py,sha256=J62xBDTaLxwBFWDmuXhzgbmZfPWaAZLr7CKsbqgTI7U,31389
|
|
11
11
|
datamint/configs.py,sha256=Bdp6NydYwyCJ2dk19_gf_o3M2ZyQOmMHpLi8wEWNHUk,1426
|
|
12
12
|
datamint/dataset/__init__.py,sha256=4PlUKSvVhdfQvvuq8jQXrkdqnot-iTTizM3aM1vgSwg,47
|
|
13
13
|
datamint/dataset/annotation.py,sha256=qN1IMjdfLD2ceQ6va3l76jOXA8Vb_c-eBk1oWQu6hW0,7994
|
|
@@ -22,7 +22,7 @@ datamint/logging.yaml,sha256=a5dsATpul7QHeUHB2TjABFjWaPXBMbO--dgn8GlRqwk,483
|
|
|
22
22
|
datamint/utils/logging_utils.py,sha256=DvoA35ATYG3JTwfXEXYawDyKRfHeCrH0a9czfkmz8kM,1851
|
|
23
23
|
datamint/utils/torchmetrics.py,sha256=lwU0nOtsSWfebyp7dvjlAggaqXtj5ohSEUXOg3L0hJE,2837
|
|
24
24
|
datamint/utils/visualization.py,sha256=yaUVAOHar59VrGUjpAWv5eVvQSfztFG0eP9p5Vt3l-M,4470
|
|
25
|
-
datamint-1.
|
|
26
|
-
datamint-1.
|
|
27
|
-
datamint-1.
|
|
28
|
-
datamint-1.
|
|
25
|
+
datamint-1.9.0.dist-info/METADATA,sha256=M1oMNcVYjTVV8tfZcxxcPFijib04QC8Zz9VBQLR7tXg,4100
|
|
26
|
+
datamint-1.9.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
27
|
+
datamint-1.9.0.dist-info/entry_points.txt,sha256=mn5H6jPjO-rY0W0CAZ6Z_KKWhMLvyVaSpoqk77jlTI4,145
|
|
28
|
+
datamint-1.9.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|