dbdicom 0.3.7__py3-none-any.whl → 0.3.8__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 dbdicom might be problematic. Click here for more details.
- dbdicom/api.py +6 -5
- dbdicom/dataset.py +14 -0
- dbdicom/dbd.py +43 -13
- {dbdicom-0.3.7.dist-info → dbdicom-0.3.8.dist-info}/METADATA +1 -1
- {dbdicom-0.3.7.dist-info → dbdicom-0.3.8.dist-info}/RECORD +8 -8
- {dbdicom-0.3.7.dist-info → dbdicom-0.3.8.dist-info}/WHEEL +0 -0
- {dbdicom-0.3.7.dist-info → dbdicom-0.3.8.dist-info}/licenses/LICENSE +0 -0
- {dbdicom-0.3.7.dist-info → dbdicom-0.3.8.dist-info}/top_level.txt +0 -0
dbdicom/api.py
CHANGED
|
@@ -198,19 +198,20 @@ def move(from_entity:list, to_entity:list):
|
|
|
198
198
|
dbd.delete(from_entity)
|
|
199
199
|
dbd.close()
|
|
200
200
|
|
|
201
|
-
def split_series(series:list, attr:Union[str, tuple])->
|
|
201
|
+
def split_series(series:list, attr:Union[str, tuple], key=None)->list:
|
|
202
202
|
"""
|
|
203
203
|
Split a series into multiple series
|
|
204
204
|
|
|
205
205
|
Args:
|
|
206
206
|
series (list): series to split.
|
|
207
|
-
attr (str or tuple): dicom attribute to split the series by.
|
|
207
|
+
attr (str or tuple): dicom attribute to split the series by.
|
|
208
|
+
key (function): split by by key(attr)
|
|
208
209
|
Returns:
|
|
209
|
-
|
|
210
|
-
and
|
|
210
|
+
list: list of two-element tuples, where the first element is
|
|
211
|
+
is the value and the second element is the series corresponding to that value.
|
|
211
212
|
"""
|
|
212
213
|
dbd = open(series[0])
|
|
213
|
-
split_series = dbd.split_series(series, attr)
|
|
214
|
+
split_series = dbd.split_series(series, attr, key)
|
|
214
215
|
dbd.close()
|
|
215
216
|
return split_series
|
|
216
217
|
|
dbdicom/dataset.py
CHANGED
|
@@ -344,10 +344,24 @@ def format_value(value, VR=None, tag=None):
|
|
|
344
344
|
#return value[:64]
|
|
345
345
|
if VR == 'TM':
|
|
346
346
|
return variables.seconds_to_str(value)
|
|
347
|
+
if VR == 'DA':
|
|
348
|
+
if not is_valid_dicom_date(value):
|
|
349
|
+
return '99991231'
|
|
347
350
|
|
|
348
351
|
return value
|
|
349
352
|
|
|
350
353
|
|
|
354
|
+
|
|
355
|
+
def is_valid_dicom_date(da_str: str) -> bool:
|
|
356
|
+
if not isinstance(da_str, str) or len(da_str) != 8 or not da_str.isdigit():
|
|
357
|
+
return False
|
|
358
|
+
try:
|
|
359
|
+
datetime.strptime(da_str, "%Y%m%d")
|
|
360
|
+
return True
|
|
361
|
+
except ValueError:
|
|
362
|
+
return False
|
|
363
|
+
|
|
364
|
+
|
|
351
365
|
def check_value(value, tag):
|
|
352
366
|
|
|
353
367
|
# If the change below is made (TM, DA, DT) then this needs to
|
dbdicom/dbd.py
CHANGED
|
@@ -3,6 +3,7 @@ from datetime import datetime
|
|
|
3
3
|
import json
|
|
4
4
|
from typing import Union
|
|
5
5
|
import zipfile
|
|
6
|
+
import re
|
|
6
7
|
|
|
7
8
|
from tqdm import tqdm
|
|
8
9
|
import numpy as np
|
|
@@ -651,37 +652,43 @@ class DataBaseDicom():
|
|
|
651
652
|
self.delete(from_entity)
|
|
652
653
|
return self
|
|
653
654
|
|
|
654
|
-
def split_series(self, series:list, attr:Union[str, tuple]) ->
|
|
655
|
+
def split_series(self, series:list, attr:Union[str, tuple], key=None) -> list:
|
|
655
656
|
"""
|
|
656
657
|
Split a series into multiple series
|
|
657
658
|
|
|
658
659
|
Args:
|
|
659
660
|
series (list): series to split.
|
|
660
661
|
attr (str or tuple): dicom attribute to split the series by.
|
|
662
|
+
key (function): split by by key(attr)
|
|
661
663
|
Returns:
|
|
662
|
-
|
|
663
|
-
and
|
|
664
|
+
list: list of two-element tuples, where the first element is
|
|
665
|
+
is the value and the second element is the series corresponding to that value.
|
|
664
666
|
"""
|
|
665
667
|
|
|
666
668
|
# Find all values of the attr and list files per value
|
|
667
669
|
all_files = register.files(self.register, series)
|
|
668
|
-
files =
|
|
670
|
+
files = []
|
|
671
|
+
values = []
|
|
669
672
|
for f in tqdm(all_files, desc=f'Reading {attr}'):
|
|
670
673
|
ds = dbdataset.read_dataset(f)
|
|
671
674
|
v = dbdataset.get_values(ds, attr)
|
|
672
|
-
if
|
|
673
|
-
|
|
675
|
+
if key is not None:
|
|
676
|
+
v = key(v)
|
|
677
|
+
if v in values:
|
|
678
|
+
index = values.index(v)
|
|
679
|
+
files[index].append(f)
|
|
674
680
|
else:
|
|
675
|
-
|
|
681
|
+
values.append(v)
|
|
682
|
+
files.append([f])
|
|
676
683
|
|
|
677
684
|
# Copy the files for each value (sorted) to new series
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
for v in tqdm(values, desc='Writing new series'):
|
|
685
|
+
split_series = []
|
|
686
|
+
for index, v in tqdm(enumerate(values), desc='Writing new series'):
|
|
681
687
|
series_desc = series[-1] if isinstance(series, str) else series[-1][0]
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
688
|
+
series_desc = clean_folder_name(f'{series_desc}_{attr}_{v}')
|
|
689
|
+
series_v = series[:3] + [(series_desc, 0)]
|
|
690
|
+
self._files_to_series(files[index], series_v)
|
|
691
|
+
split_series.append((v, series_v))
|
|
685
692
|
return split_series
|
|
686
693
|
|
|
687
694
|
|
|
@@ -910,6 +917,29 @@ class DataBaseDicom():
|
|
|
910
917
|
|
|
911
918
|
|
|
912
919
|
|
|
920
|
+
def clean_folder_name(name, replacement="", max_length=255):
|
|
921
|
+
# Strip leading/trailing whitespace
|
|
922
|
+
name = name.strip()
|
|
923
|
+
|
|
924
|
+
# Replace invalid characters (Windows, macOS, Linux-safe)
|
|
925
|
+
illegal_chars = r'[<>:"/\\|?*\[\]\x00-\x1F\x7F]'
|
|
926
|
+
name = re.sub(illegal_chars, replacement, name)
|
|
927
|
+
|
|
928
|
+
# Replace reserved Windows names
|
|
929
|
+
reserved = {
|
|
930
|
+
"CON", "PRN", "AUX", "NUL",
|
|
931
|
+
*(f"COM{i}" for i in range(1, 10)),
|
|
932
|
+
*(f"LPT{i}" for i in range(1, 10))
|
|
933
|
+
}
|
|
934
|
+
name_upper = name.upper().split(".")[0] # Just base name
|
|
935
|
+
if name_upper in reserved:
|
|
936
|
+
name = f"{name}_folder"
|
|
937
|
+
|
|
938
|
+
# Truncate to max length (common max: 255 bytes)
|
|
939
|
+
return name[:max_length] or "folder"
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
|
|
913
943
|
def infer_slice_spacing(vols):
|
|
914
944
|
# In case spacing between slices is not (correctly) encoded in
|
|
915
945
|
# DICOM it can be inferred from the slice locations.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dbdicom
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.8
|
|
4
4
|
Summary: A pythonic interface for reading and writing DICOM databases
|
|
5
5
|
Author-email: Steven Sourbron <s.sourbron@sheffield.ac.uk>, Ebony Gunwhy <e.gunwhy@sheffield.ac.uk>
|
|
6
6
|
Project-URL: Homepage, https://openmiblab.github.io/dbdicom/
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
dbdicom/__init__.py,sha256=dW5aezonmMc_41Dp1PuYmXQlr307RkyJxsJuetkpWso,87
|
|
2
|
-
dbdicom/api.py,sha256=
|
|
2
|
+
dbdicom/api.py,sha256=VA0rXXax30v_ZZ2M-TM_6w4SaV0zqc--5J4w9kUqSyc,14220
|
|
3
3
|
dbdicom/const.py,sha256=BqBiRRjeiSqDr1W6YvaayD8WKCjG4Cny2NT0GeLM6bI,4269
|
|
4
4
|
dbdicom/database.py,sha256=_LUbH7gc9l7j_63AC71DjwxgTUwbEjHSy5kuvRw75Hw,4764
|
|
5
|
-
dbdicom/dataset.py,sha256=
|
|
6
|
-
dbdicom/dbd.py,sha256=
|
|
5
|
+
dbdicom/dataset.py,sha256=hDw6aZ3PF-k5wdR2CBBL_ZtvtDBWWrjKvaKKPfs-yYg,23146
|
|
6
|
+
dbdicom/dbd.py,sha256=6F2uC00KzweRCUQnCVBm-Co-QF-KqxfZUFjQxTnUEi0,39291
|
|
7
7
|
dbdicom/register.py,sha256=_NyNbOEAN_hkwjxupNpr9F5DWUwARCsci8knK41-EsA,13931
|
|
8
8
|
dbdicom/external/__init__.py,sha256=XNQqfspyf6vFGedXlRKZsUB8k8E-0W19Uamwn8Aioxo,316
|
|
9
9
|
dbdicom/external/__pycache__/__init__.cpython-311.pyc,sha256=pXAQ35ixd92fm6YcuHgzR1t6RcASQ-cHhU1wOA5b8sw,542
|
|
@@ -47,8 +47,8 @@ dbdicom/utils/dcm4che.py,sha256=Vxq8NYWWK3BuqJkzhBQ89oMqzJlnxqTxgsgTo_Frznc,2317
|
|
|
47
47
|
dbdicom/utils/files.py,sha256=qhWNJqeWnRjDNbERpC6Mz962_TW9mFdvd2lnBbK3xt4,2259
|
|
48
48
|
dbdicom/utils/image.py,sha256=qsU_wOdleZCqU5g7LSp8OXKmoG109NauYx7wad_ZQ7Q,3839
|
|
49
49
|
dbdicom/utils/variables.py,sha256=vUh5cDnmCft5hoXDYXUvfkg5Cy5WlgMAogU38Y_BKRo,5753
|
|
50
|
-
dbdicom-0.3.
|
|
51
|
-
dbdicom-0.3.
|
|
52
|
-
dbdicom-0.3.
|
|
53
|
-
dbdicom-0.3.
|
|
54
|
-
dbdicom-0.3.
|
|
50
|
+
dbdicom-0.3.8.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
51
|
+
dbdicom-0.3.8.dist-info/METADATA,sha256=QQLXmSX2KJ5-on3wW3ORtelkKawriWolIzntBzb8Y5k,1030
|
|
52
|
+
dbdicom-0.3.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
53
|
+
dbdicom-0.3.8.dist-info/top_level.txt,sha256=nJWxXg4YjD6QblfmhrzTMXcr8FSKNc0Yk-CAIDUsYkQ,8
|
|
54
|
+
dbdicom-0.3.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|