dbdicom 0.3.7__tar.gz → 0.3.8__tar.gz

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.

Files changed (62) hide show
  1. {dbdicom-0.3.7/src/dbdicom.egg-info → dbdicom-0.3.8}/PKG-INFO +1 -1
  2. {dbdicom-0.3.7 → dbdicom-0.3.8}/pyproject.toml +1 -1
  3. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/api.py +6 -5
  4. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/dataset.py +14 -0
  5. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/dbd.py +43 -13
  6. {dbdicom-0.3.7 → dbdicom-0.3.8/src/dbdicom.egg-info}/PKG-INFO +1 -1
  7. {dbdicom-0.3.7 → dbdicom-0.3.8}/LICENSE +0 -0
  8. {dbdicom-0.3.7 → dbdicom-0.3.8}/MANIFEST.in +0 -0
  9. {dbdicom-0.3.7 → dbdicom-0.3.8}/README.rst +0 -0
  10. {dbdicom-0.3.7 → dbdicom-0.3.8}/setup.cfg +0 -0
  11. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/__init__.py +0 -0
  12. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/const.py +0 -0
  13. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/database.py +0 -0
  14. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/__init__.py +0 -0
  15. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/__pycache__/__init__.cpython-311.pyc +0 -0
  16. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/README.md +0 -0
  17. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/__init__.py +0 -0
  18. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/__pycache__/__init__.cpython-311.pyc +0 -0
  19. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/bin/__init__.py +0 -0
  20. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-311.pyc +0 -0
  21. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/bin/deidentify +0 -0
  22. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/bin/deidentify.bat +0 -0
  23. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/bin/emf2sf +0 -0
  24. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/bin/emf2sf.bat +0 -0
  25. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/etc/__init__.py +0 -0
  26. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/etc/emf2sf/__init__.py +0 -0
  27. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/etc/emf2sf/log4j.properties +0 -0
  28. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/__init__.py +0 -0
  29. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/commons-cli-1.4.jar +0 -0
  30. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/dcm4che-core-5.23.1.jar +0 -0
  31. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/dcm4che-emf-5.23.1.jar +0 -0
  32. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/dcm4che-tool-common-5.23.1.jar +0 -0
  33. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/dcm4che-tool-emf2sf-5.23.1.jar +0 -0
  34. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/log4j-1.2.17.jar +0 -0
  35. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/macosx-x86-64/libopencv_java.jnilib +0 -0
  36. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/slf4j-api-1.7.30.jar +0 -0
  37. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/slf4j-log4j12-1.7.30.jar +0 -0
  38. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/windows-x86/clib_jiio.dll +0 -0
  39. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/windows-x86/clib_jiio_sse2.dll +0 -0
  40. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/windows-x86/clib_jiio_util.dll +0 -0
  41. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/windows-x86/opencv_java.dll +0 -0
  42. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/external/dcm4che/lib/windows-x86-64/opencv_java.dll +0 -0
  43. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/register.py +0 -0
  44. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/sop_classes/ct_image.py +0 -0
  45. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/sop_classes/enhanced_mr_image.py +0 -0
  46. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/sop_classes/mr_image.py +0 -0
  47. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/sop_classes/parametric_map.py +0 -0
  48. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/sop_classes/secondary_capture.py +0 -0
  49. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/sop_classes/segmentation.py +0 -0
  50. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/sop_classes/ultrasound_multiframe_image.py +0 -0
  51. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/sop_classes/xray_angiographic_image.py +0 -0
  52. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/utils/arrays.py +0 -0
  53. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/utils/dcm4che.py +0 -0
  54. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/utils/files.py +0 -0
  55. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/utils/image.py +0 -0
  56. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom/utils/variables.py +0 -0
  57. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom.egg-info/SOURCES.txt +0 -0
  58. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom.egg-info/dependency_links.txt +0 -0
  59. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom.egg-info/requires.txt +0 -0
  60. {dbdicom-0.3.7 → dbdicom-0.3.8}/src/dbdicom.egg-info/top_level.txt +0 -0
  61. {dbdicom-0.3.7 → dbdicom-0.3.8}/tests/test_api.py +0 -0
  62. {dbdicom-0.3.7 → dbdicom-0.3.8}/tests/test_dcm4che.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbdicom
3
- Version: 0.3.7
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/
@@ -7,7 +7,7 @@ requires = ['setuptools>=61.2']
7
7
 
8
8
  [project]
9
9
  name = "dbdicom"
10
- version = "0.3.7"
10
+ version = "0.3.8"
11
11
  dependencies = [
12
12
  "tqdm",
13
13
  "importlib-resources",
@@ -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])->dict:
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
- dict: dictionary with keys the unique values found (ascending)
210
- and as values the series corresponding to that value.
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
 
@@ -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
@@ -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]) -> dict:
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
- dict: dictionary with keys the unique values found (ascending)
663
- and as values the series corresponding to that value.
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 v in files:
673
- files[v].append(f)
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
- files[v] = [f]
681
+ values.append(v)
682
+ files.append([f])
676
683
 
677
684
  # Copy the files for each value (sorted) to new series
678
- values = sorted(list(files.keys()))
679
- split_series = {}
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
- series_v = series[:3] + [f'{series_desc}_{attr}_{v}']
683
- self._files_to_series(files[v], series_v)
684
- split_series[v] = series_v
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.7
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/
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes