dbdicom 0.3.0__py3-none-any.whl → 0.3.1__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 CHANGED
@@ -24,6 +24,7 @@ def print(path):
24
24
  """
25
25
  dbd = open(path)
26
26
  dbd.print()
27
+ dbd.close()
27
28
 
28
29
 
29
30
  def summary(path) -> dict:
@@ -36,7 +37,9 @@ def summary(path) -> dict:
36
37
  dict: Nested dictionary with summary information on the database.
37
38
  """
38
39
  dbd = open(path)
39
- return dbd.summary()
40
+ s = dbd.summary()
41
+ dbd.close()
42
+ return s
40
43
 
41
44
 
42
45
  def patients(path, name:str=None, contains:str=None, isin:list=None)->list:
@@ -56,7 +59,9 @@ def patients(path, name:str=None, contains:str=None, isin:list=None)->list:
56
59
  list: list of patients fulfilling the criteria.
57
60
  """
58
61
  dbd = open(path)
59
- return dbd.patients(name, contains, isin)
62
+ p = dbd.patients(name, contains, isin)
63
+ dbd.close()
64
+ return p
60
65
 
61
66
 
62
67
  def studies(entity:str | list, name:str=None, contains:str=None, isin:list=None)->list:
@@ -79,10 +84,14 @@ def studies(entity:str | list, name:str=None, contains:str=None, isin:list=None)
79
84
  """
80
85
  if isinstance(entity, str): # path = folder
81
86
  dbd = open(entity)
82
- return dbd.studies(entity, name, contains, isin)
87
+ s = dbd.studies(entity, name, contains, isin)
88
+ dbd.close()
89
+ return s
83
90
  elif len(entity)==2: # path = patient
84
91
  dbd = open(entity[0])
85
- return dbd.studies(entity, name, contains, isin)
92
+ s = dbd.studies(entity, name, contains, isin)
93
+ dbd.close()
94
+ return s
86
95
  else:
87
96
  raise ValueError(
88
97
  "The path must be a folder or a 2-element list "
@@ -110,10 +119,14 @@ def series(entity:str | list, name:str=None, contains:str=None, isin:list=None)-
110
119
  """
111
120
  if isinstance(entity, str): # path = folder
112
121
  dbd = open(entity)
113
- return dbd.series(entity, name, contains, isin)
122
+ s = dbd.series(entity, name, contains, isin)
123
+ dbd.close()
124
+ return s
114
125
  elif len(entity) in [2,3]:
115
126
  dbd = open(entity[0])
116
- return dbd.series(entity, name, contains, isin)
127
+ s = dbd.series(entity, name, contains, isin)
128
+ dbd.close()
129
+ return s
117
130
  else:
118
131
  raise ValueError(
119
132
  "To retrieve a series, the entity must be a database, patient or study."
@@ -168,7 +181,9 @@ def volume(series:list, dims:list=None, multislice=False) -> vreg.Volume3D:
168
181
  vreg.Volume3D: vole read from the series.
169
182
  """
170
183
  dbd = open(series[0])
171
- return dbd.volume(series, dims, multislice)
184
+ vol = dbd.volume(series, dims, multislice)
185
+ dbd.close()
186
+ return vol
172
187
 
173
188
  def write_volume(vol:vreg.Volume3D, series:list, ref:list=None,
174
189
  multislice=False):
@@ -200,6 +215,7 @@ def to_nifti(series:list, file:str, dims:list=None, multislice=False):
200
215
  """
201
216
  dbd = open(series[0])
202
217
  dbd.to_nifti(series, file, dims, multislice)
218
+ dbd.close()
203
219
 
204
220
  def from_nifti(file:str, series:list, ref:list=None, multislice=False):
205
221
  """Create a DICOM series from a nifti file.
@@ -232,7 +248,9 @@ def pixel_data(series:list, dims:list=None, include:list=None) -> tuple:
232
248
  return value.
233
249
  """
234
250
  dbd = open(series[0])
235
- return dbd.pixel_data(series, dims, include)
251
+ array = dbd.pixel_data(series, dims, include)
252
+ dbd.close()
253
+ return array
236
254
 
237
255
  # write_pixel_data()
238
256
  # values()
@@ -255,7 +273,9 @@ def unique(pars:list, entity:list) -> dict:
255
273
  dict: dictionary with unique values for each attribute.
256
274
  """
257
275
  dbd = open(entity[0])
258
- return dbd.unique(pars, entity)
276
+ u = dbd.unique(pars, entity)
277
+ dbd.close()
278
+ return u
259
279
 
260
280
 
261
281
 
dbdicom/dataset.py CHANGED
@@ -1,3 +1,6 @@
1
+ # Test data
2
+ # https://www.aliza-dicom-viewer.com/download/datasets
3
+
1
4
  import os
2
5
  from datetime import datetime
3
6
  import struct
@@ -712,41 +715,7 @@ def set_signal_type(ds, value):
712
715
 
713
716
 
714
717
 
718
+ if __name__=='__main__':
715
719
 
716
- # def _initialize(ds, UID=None, ref=None): # ds is pydicom dataset
717
-
718
- # # Date and Time of Creation
719
- # dt = datetime.now()
720
- # timeStr = dt.strftime('%H%M%S') # long format with micro seconds
721
-
722
- # ds.ContentDate = dt.strftime('%Y%m%d')
723
- # ds.ContentTime = timeStr
724
- # ds.AcquisitionDate = dt.strftime('%Y%m%d')
725
- # ds.AcquisitionTime = timeStr
726
- # ds.SeriesDate = dt.strftime('%Y%m%d')
727
- # ds.SeriesTime = timeStr
728
- # ds.InstanceCreationDate = dt.strftime('%Y%m%d')
729
- # ds.InstanceCreationTime = timeStr
730
-
731
- # if UID is not None:
732
-
733
- # # overwrite UIDs
734
- # ds.PatientID = UID[0]
735
- # ds.StudyInstanceUID = UID[1]
736
- # ds.SeriesInstanceUID = UID[2]
737
- # ds.SOPInstanceUID = UID[3]
738
-
739
- # if ref is not None:
740
-
741
- # # Series, Instance and Class for Reference
742
- # refd_instance = Dataset()
743
- # refd_instance.ReferencedSOPClassUID = ref.SOPClassUID
744
- # refd_instance.ReferencedSOPInstanceUID = ref.SOPInstanceUID
745
-
746
- # refd_series = Dataset()
747
- # refd_series.ReferencedInstanceSequence = Sequence([refd_instance])
748
- # refd_series.SeriesInstanceUID = ds.SeriesInstanceUID
749
-
750
- # ds.ReferencedSeriesSequence = Sequence([refd_series])
751
-
752
- # return ds
720
+ pass
721
+ #codify('C:\\Users\\md1spsx\\Documents\\f32bit.dcm', 'C:\\Users\\md1spsx\\Documents\\f32bit.py')
dbdicom/dbd.py CHANGED
@@ -343,26 +343,38 @@ class DataBaseDicom():
343
343
  self.write_volume(vol, series, ref, multislice)
344
344
  return self
345
345
 
346
- def pixel_data(self, series:list, dims:list=None, include=None) -> np.ndarray:
346
+ def pixel_data(self, series:list, dims:list=None, coords=False, include=None) -> np.ndarray:
347
347
  """Read the pixel data from a DICOM series
348
348
 
349
349
  Args:
350
350
  series (list): DICOM series to read
351
351
  dims (list, optional): Dimensions of the array.
352
+ coords (bool): If set to Trye, the coordinates of the
353
+ arrays are returned alongside the pixel data
352
354
  include (list, optional): list of DICOM attributes that are
353
355
  read on the fly to avoid reading the data twice.
354
356
 
355
357
  Returns:
356
- tuple: numpy array with pixel values and an array with
358
+ numpy.ndarray or tuple: numpy array with pixel values, with
359
+ at least 3 dimensions (x,y,z). If
360
+ coords is set these are returned too as an array with
357
361
  coordinates of the slices according to dims. If include
358
- is provide these are returned as a dictionary in a third
362
+ is provide the values are returned as a dictionary in the last
359
363
  return value.
360
364
  """
365
+ if coords:
366
+ if dims is None:
367
+ raise ValueError(
368
+ "Coordinates can only be returned if dimensions are specified."
369
+ )
361
370
 
362
- if np.isscalar(dims):
371
+ if dims is None:
372
+ dims = []
373
+ elif np.isscalar(dims):
363
374
  dims = [dims]
364
375
  else:
365
376
  dims = list(dims)
377
+ dims = ['SliceLocation'] + dims
366
378
 
367
379
  # Ensure return_vals is a list
368
380
  if include is None:
@@ -375,34 +387,40 @@ class DataBaseDicom():
375
387
  files = register.files(self.register, series)
376
388
 
377
389
  # Read dicom files
378
- coords = []
390
+ coords_array = []
379
391
  arrays = np.empty(len(files), dtype=dict)
380
392
  if include is not None:
381
393
  values = np.empty(len(files), dtype=dict)
382
394
  for i, f in tqdm(enumerate(files), desc='Reading pixel data..'):
383
395
  ds = dbdataset.read_dataset(f)
384
- coords.append(dbdataset.get_values(ds, dims))
396
+ coords_array.append(dbdataset.get_values(ds, dims))
385
397
  # save as dict so numpy does not stack as arrays
386
398
  arrays[i] = {'pixel_data': dbdataset.pixel_data(ds)}
387
399
  if include is not None:
388
400
  values[i] = {'values': dbdataset.get_values(ds, params)}
389
401
 
390
402
  # Format as mesh
391
- coords = np.stack([v for v in coords], axis=-1)
392
- coords, inds = dbdicom.utils.arrays.meshvals(coords)
403
+ coords_array = np.stack([v for v in coords_array], axis=-1)
404
+ coords_array, inds = dbdicom.utils.arrays.meshvals(coords_array)
393
405
 
394
- arrays = arrays[inds].reshape(coords.shape[1:])
406
+ arrays = arrays[inds].reshape(coords_array.shape[1:])
395
407
  arrays = np.stack([a['pixel_data'] for a in arrays.reshape(-1)], axis=-1)
396
- arrays = arrays.reshape(arrays.shape[:2] + coords.shape[1:])
408
+ arrays = arrays.reshape(arrays.shape[:2] + coords_array.shape[1:])
397
409
 
398
410
  if include is None:
399
- return arrays, coords
411
+ if coords:
412
+ return arrays, coords_array[1:,...]
413
+ else:
414
+ return arrays
400
415
 
401
- values = values[inds].reshape(coords.shape[1:])
416
+ values = values[inds].reshape(coords_array.shape[1:])
402
417
  values = np.stack([a['values'] for a in values.reshape(-1)], axis=-1)
403
- values = values.reshape((len(params), ) + coords.shape[1:])
418
+ values = values.reshape((len(params), ) + coords_array.shape[1:])
404
419
 
405
- return arrays, coords, values
420
+ if coords:
421
+ return arrays, coords_array[1:,...], values
422
+ else:
423
+ return arrays, values
406
424
 
407
425
 
408
426
  def unique(self, pars:list, entity:list) -> dict:
@@ -695,8 +713,7 @@ class DataBaseDicom():
695
713
  """
696
714
  # For each series, check if there are multiple
697
715
  # SOP Classes in the series and split them if yes.
698
- all_series = self.series()
699
- for series in tqdm(all_series, desc='Splitting series with multiple SOP Classes.'):
716
+ for series in self.series():
700
717
  series_index = register.index(self.register, series)
701
718
  df_series = self.register.loc[series_index]
702
719
  sop_classes = df_series.SOPClassUID.unique()
@@ -704,7 +721,7 @@ class DataBaseDicom():
704
721
  # For each sop_class, create a new series and move all
705
722
  # instances of that sop_class to the new series
706
723
  desc = series[-1] if isinstance(series, str) else series[0]
707
- for i, sop_class in enumerate(sop_classes[1:]):
724
+ for i, sop_class in tqdm(enumerate(sop_classes[1:]), desc='Splitting series with multiple SOP Classes.'):
708
725
  df_sop_class = df_series[df_series.SOPClassUID == sop_class]
709
726
  relpaths = df_sop_class.index.tolist()
710
727
  sop_class_files = [os.path.join(self.path, p) for p in relpaths]
@@ -6,6 +6,9 @@ from pydicom.uid import generate_uid, ParametricMapStorage
6
6
  from datetime import datetime
7
7
 
8
8
 
9
+ def from_volume(vol):
10
+ pass
11
+
9
12
 
10
13
  def create_parametric_map(rows=64, cols=64, frames=1):
11
14
  # Create dummy pixel data (floating point)
@@ -57,7 +60,7 @@ def create_parametric_map(rows=64, cols=64, frames=1):
57
60
  ds.HighBit = 31
58
61
  ds.PixelRepresentation = 1 # 1 = signed, 0 = unsigned
59
62
  ds.FloatPixelData = pixel_array.astype(np.float32).tobytes()
60
- ds.PixelData = b'' # Actual data goes in FloatPixelData
63
+ ds.PixelData = b"\0" * rows * cols * frames # Actual data goes in FloatPixelData
61
64
 
62
65
  # Functional Group Sequences (minimal dummy values)
63
66
  ds.SharedFunctionalGroupsSequence = [Dataset()]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbdicom
3
- Version: 0.3.0
3
+ Version: 0.3.1
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,20 +1,20 @@
1
1
  dbdicom/__init__.py,sha256=DyogeTraV6o-FgWdBCbtVEaMmdkMQHkYkraDIE0t8OA,25
2
- dbdicom/api.py,sha256=_baV2dR9Szay4z2_JY-QmTB9gTTc_PB7OzzgqRwmYHg,8945
2
+ dbdicom/api.py,sha256=sxQYjNu4q0gGAQ5jcE2yCpMKJnMjniTGsqwrGSQdMsU,9275
3
3
  dbdicom/const.py,sha256=BqBiRRjeiSqDr1W6YvaayD8WKCjG4Cny2NT0GeLM6bI,4269
4
- dbdicom/dataset.py,sha256=IVTLq4pTydwKjS9-xCQAqiSd0Xm63JxCxos4HemtuVs,23945
5
- dbdicom/dbd.py,sha256=MKZDnQu1R0s1RlJ5VAKcty4UFmtMg6aXz9epjLilYzc,29001
4
+ dbdicom/dataset.py,sha256=fPKemmsJSaoyZHO-xdxvVtd4Rlh5m6rR63YkKuIFYAo,22874
5
+ dbdicom/dbd.py,sha256=Y4BMR9QATz1Y4HhvPOw-pB8ps4D7Z8584PKOJQE9tzM,29768
6
6
  dbdicom/register.py,sha256=Nt-Q3Nvb72qRqSL1ervuunp2LBuOZEs-K8YUqihR_oQ,21210
7
7
  dbdicom/external/__init__.py,sha256=XNQqfspyf6vFGedXlRKZsUB8k8E-0W19Uamwn8Aioxo,316
8
- dbdicom/external/__pycache__/__init__.cpython-311.pyc,sha256=tvFkDCXniSXAqkZTFggZPxaPTVgaRmpeGYZlZw0Ibhc,534
8
+ dbdicom/external/__pycache__/__init__.cpython-311.pyc,sha256=cIySrImYKo1fJP3-0ZMV-5ZKcZEEDX-uwfZ7I4U-jRs,534
9
9
  dbdicom/external/dcm4che/README.md,sha256=0aAGRs36W3_0s5LzWHRGf_tqariS_JP4iJggaxnD4Xw,8987
10
10
  dbdicom/external/dcm4che/__init__.py,sha256=YwpeMCLrxffGOkchsGjgAuB6ia3VX_tx9Y7ru9EWtoY,35
11
- dbdicom/external/dcm4che/__pycache__/__init__.cpython-311.pyc,sha256=qbKEVGsXw9bmCxsR6KssmR3ZoGJAkkVv5LQ2eFVhs5M,248
11
+ dbdicom/external/dcm4che/__pycache__/__init__.cpython-311.pyc,sha256=QsnVh0zH1ZSOoNwtTqiirWH8CB0b2eJ0DEvgVoVhZ0Y,248
12
12
  dbdicom/external/dcm4che/bin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  dbdicom/external/dcm4che/bin/deidentify,sha256=64MNIEpp-CWzFSb6TV0KtyCBvD7XyEsovRjBeyxDqSc,1698
14
14
  dbdicom/external/dcm4che/bin/deidentify.bat,sha256=kVXUkcy1C4Y3KjC2NJwmmR0pufSJWmaof_LR5CTAxMg,1455
15
15
  dbdicom/external/dcm4che/bin/emf2sf,sha256=svCzkZ-QhdVTV0NNHOpBiwNBMODVWZHJIFA7cWaN2bM,1622
16
16
  dbdicom/external/dcm4che/bin/emf2sf.bat,sha256=Vh0ry9KNJX_WXcyCrLSxbJ_6Crot9rjmwi__u2GZqLY,1375
17
- dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-311.pyc,sha256=NnB9_qHwjxDZrdid-_YGOWCzkEy8p9ka3FHiCUtFX-M,195
17
+ dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-311.pyc,sha256=M2mla4vNW1gSUWQps3dx4g8NRd4BaQJLP1OKQHmi6Sk,195
18
18
  dbdicom/external/dcm4che/etc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  dbdicom/external/dcm4che/etc/emf2sf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  dbdicom/external/dcm4che/etc/emf2sf/log4j.properties,sha256=3hHcBFt2oNRjvHtix5bfuEsnKfdv5IYOkbsyoY9g7cM,223
@@ -36,7 +36,7 @@ dbdicom/external/dcm4che/lib/windows-x86-64/opencv_java.dll,sha256=TmjW2SbG4MR3G
36
36
  dbdicom/sop_classes/ct_image.py,sha256=16PNv_0e1_7cfxE12JWlx5YQeaTAQVzwtXTjxs3aonk,2812
37
37
  dbdicom/sop_classes/enhanced_mr_image.py,sha256=13j4EGXniBpJxpzzL3Xa4y3g5OKhMd5Ct7cjPGOYQY4,35496
38
38
  dbdicom/sop_classes/mr_image.py,sha256=6V2OyjwkaZxoljImNREU0Du4NJLHHsY_GgOe2XQsmNg,10683
39
- dbdicom/sop_classes/parametric_map.py,sha256=eyJdHUxh9KUI7qPaGANU2H3R1Br4CH0XHmRIGvrsKY8,10220
39
+ dbdicom/sop_classes/parametric_map.py,sha256=ayNMpeBbc-neVGDjEAe5ww_UYJvbRmk46rHa_CjwZao,10280
40
40
  dbdicom/sop_classes/secondary_capture.py,sha256=wgNRX8qyhV7HR7Jq2tQWPPuGpiRzYl6qPOgK6qFbPUc,4541
41
41
  dbdicom/sop_classes/segmentation.py,sha256=I8-PciIoIz27_-dZ4esBZSw0TBBbO8KbNYTiTmVe62g,11465
42
42
  dbdicom/sop_classes/ultrasound_multiframe_image.py,sha256=j3KN5R90j6WwPMy01hAN2_XSum5TvksF2MYoNGfX_yE,2797
@@ -46,8 +46,8 @@ dbdicom/utils/dcm4che.py,sha256=Vxq8NYWWK3BuqJkzhBQ89oMqzJlnxqTxgsgTo_Frznc,2317
46
46
  dbdicom/utils/files.py,sha256=qhWNJqeWnRjDNbERpC6Mz962_TW9mFdvd2lnBbK3xt4,2259
47
47
  dbdicom/utils/image.py,sha256=s1P8m-s64ygKSh_X4DdV96LC4DvCe3KO3_71l72zWoU,4057
48
48
  dbdicom/utils/variables.py,sha256=vUh5cDnmCft5hoXDYXUvfkg5Cy5WlgMAogU38Y_BKRo,5753
49
- dbdicom-0.3.0.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
50
- dbdicom-0.3.0.dist-info/METADATA,sha256=0NHxTTJitzp6e80Ly6NFWNsAepbjRTQWsBk0L-FqsbE,1075
51
- dbdicom-0.3.0.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
52
- dbdicom-0.3.0.dist-info/top_level.txt,sha256=nJWxXg4YjD6QblfmhrzTMXcr8FSKNc0Yk-CAIDUsYkQ,8
53
- dbdicom-0.3.0.dist-info/RECORD,,
49
+ dbdicom-0.3.1.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
50
+ dbdicom-0.3.1.dist-info/METADATA,sha256=97Xgzc6BE9N3ygBO59psUqmVs9TTZ9iw7o2dUMJSFfQ,1075
51
+ dbdicom-0.3.1.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
52
+ dbdicom-0.3.1.dist-info/top_level.txt,sha256=nJWxXg4YjD6QblfmhrzTMXcr8FSKNc0Yk-CAIDUsYkQ,8
53
+ dbdicom-0.3.1.dist-info/RECORD,,