dbdicom 0.3.7__tar.gz → 0.3.9__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 (64) hide show
  1. {dbdicom-0.3.7/src/dbdicom.egg-info → dbdicom-0.3.9}/PKG-INFO +1 -1
  2. {dbdicom-0.3.7 → dbdicom-0.3.9}/pyproject.toml +1 -1
  3. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/api.py +12 -9
  4. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/database.py +2 -2
  5. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/dataset.py +29 -301
  6. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/dbd.py +95 -51
  7. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/sop_classes/enhanced_mr_image.py +190 -271
  8. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/utils/image.py +13 -13
  9. dbdicom-0.3.9/src/dbdicom/utils/pydicom_dataset.py +386 -0
  10. {dbdicom-0.3.7 → dbdicom-0.3.9/src/dbdicom.egg-info}/PKG-INFO +1 -1
  11. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom.egg-info/SOURCES.txt +3 -2
  12. {dbdicom-0.3.7 → dbdicom-0.3.9}/tests/test_api.py +32 -0
  13. dbdicom-0.3.9/tests/test_sop_classes.py +33 -0
  14. dbdicom-0.3.7/src/dbdicom/utils/variables.py +0 -161
  15. {dbdicom-0.3.7 → dbdicom-0.3.9}/LICENSE +0 -0
  16. {dbdicom-0.3.7 → dbdicom-0.3.9}/MANIFEST.in +0 -0
  17. {dbdicom-0.3.7 → dbdicom-0.3.9}/README.rst +0 -0
  18. {dbdicom-0.3.7 → dbdicom-0.3.9}/setup.cfg +0 -0
  19. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/__init__.py +0 -0
  20. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/const.py +0 -0
  21. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/__init__.py +0 -0
  22. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/__pycache__/__init__.cpython-311.pyc +0 -0
  23. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/README.md +0 -0
  24. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/__init__.py +0 -0
  25. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/__pycache__/__init__.cpython-311.pyc +0 -0
  26. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/bin/__init__.py +0 -0
  27. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-311.pyc +0 -0
  28. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/bin/deidentify +0 -0
  29. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/bin/deidentify.bat +0 -0
  30. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/bin/emf2sf +0 -0
  31. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/bin/emf2sf.bat +0 -0
  32. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/etc/__init__.py +0 -0
  33. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/etc/emf2sf/__init__.py +0 -0
  34. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/etc/emf2sf/log4j.properties +0 -0
  35. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/__init__.py +0 -0
  36. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/commons-cli-1.4.jar +0 -0
  37. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/dcm4che-core-5.23.1.jar +0 -0
  38. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/dcm4che-emf-5.23.1.jar +0 -0
  39. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/dcm4che-tool-common-5.23.1.jar +0 -0
  40. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/dcm4che-tool-emf2sf-5.23.1.jar +0 -0
  41. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/log4j-1.2.17.jar +0 -0
  42. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/macosx-x86-64/libopencv_java.jnilib +0 -0
  43. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/slf4j-api-1.7.30.jar +0 -0
  44. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/slf4j-log4j12-1.7.30.jar +0 -0
  45. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/windows-x86/clib_jiio.dll +0 -0
  46. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/windows-x86/clib_jiio_sse2.dll +0 -0
  47. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/windows-x86/clib_jiio_util.dll +0 -0
  48. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/windows-x86/opencv_java.dll +0 -0
  49. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/external/dcm4che/lib/windows-x86-64/opencv_java.dll +0 -0
  50. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/register.py +0 -0
  51. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/sop_classes/ct_image.py +0 -0
  52. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/sop_classes/mr_image.py +0 -0
  53. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/sop_classes/parametric_map.py +0 -0
  54. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/sop_classes/secondary_capture.py +0 -0
  55. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/sop_classes/segmentation.py +0 -0
  56. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/sop_classes/ultrasound_multiframe_image.py +0 -0
  57. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/sop_classes/xray_angiographic_image.py +0 -0
  58. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/utils/arrays.py +0 -0
  59. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/utils/dcm4che.py +0 -0
  60. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom/utils/files.py +0 -0
  61. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom.egg-info/dependency_links.txt +0 -0
  62. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom.egg-info/requires.txt +0 -0
  63. {dbdicom-0.3.7 → dbdicom-0.3.9}/src/dbdicom.egg-info/top_level.txt +0 -0
  64. {dbdicom-0.3.7 → dbdicom-0.3.9}/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.9
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.9"
11
11
  dependencies = [
12
12
  "tqdm",
13
13
  "importlib-resources",
@@ -198,29 +198,31 @@ 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
 
217
218
 
218
- def volume(entity:Union[list, str], dims:list=None) -> Union[vreg.Volume3D, list]:
219
+ def volume(entity:Union[list, str], dims:list=None, verbose=1) -> Union[vreg.Volume3D, list]:
219
220
  """Read volume or volumes.
220
221
 
221
222
  Args:
222
223
  entity (list, str): DICOM entity to read
223
224
  dims (list, optional): Non-spatial dimensions of the volume. Defaults to None.
225
+ verbose (bool, optional): If set to 1, shows progress bar. Defaults to 1.
224
226
 
225
227
  Returns:
226
228
  vreg.Volume3D | list: If the entity is a series this returns
@@ -229,7 +231,7 @@ def volume(entity:Union[list, str], dims:list=None) -> Union[vreg.Volume3D, list
229
231
  if isinstance(entity, str):
230
232
  entity = [entity]
231
233
  dbd = open(entity[0])
232
- vol = dbd.volume(entity, dims)
234
+ vol = dbd.volume(entity, dims, verbose)
233
235
  dbd.close()
234
236
  return vol
235
237
 
@@ -245,7 +247,7 @@ def write_volume(vol:Union[vreg.Volume3D, tuple], series:list, ref:list=None):
245
247
  dbd.write_volume(vol, series, ref)
246
248
  dbd.close()
247
249
 
248
- def to_nifti(series:list, file:str, dims:list=None):
250
+ def to_nifti(series:list, file:str, dims:list=None, verbose=1):
249
251
  """Save a DICOM series in nifti format.
250
252
 
251
253
  Args:
@@ -253,9 +255,10 @@ def to_nifti(series:list, file:str, dims:list=None):
253
255
  file (str): file path of the nifti file.
254
256
  dims (list, optional): Non-spatial dimensions of the volume.
255
257
  Defaults to None.
258
+ verbose (bool, optional): If set to 1, shows progress bar. Defaults to 1.
256
259
  """
257
260
  dbd = open(series[0])
258
- dbd.to_nifti(series, file, dims)
261
+ dbd.to_nifti(series, file, dims, verbose)
259
262
  dbd.close()
260
263
 
261
264
  def from_nifti(file:str, series:list, ref:list=None):
@@ -7,7 +7,7 @@ import pydicom
7
7
 
8
8
  import dbdicom.utils.dcm4che as dcm4che
9
9
  import dbdicom.utils.files as filetools
10
- import dbdicom.dataset as dbdataset
10
+ from dbdicom.utils.pydicom_dataset import get_values
11
11
 
12
12
 
13
13
  COLUMNS = [
@@ -41,7 +41,7 @@ def read(path):
41
41
  if 'TransferSyntaxUID' in ds.file_meta:
42
42
  if not 'Rows' in ds: # Image only
43
43
  continue
44
- row = dbdataset.get_values(ds, tags)
44
+ row = get_values(ds, tags)
45
45
  array.append(row)
46
46
  index = os.path.relpath(file, path)
47
47
  dicom_files.append(index)
@@ -2,19 +2,18 @@
2
2
  # https://www.aliza-dicom-viewer.com/download/datasets
3
3
 
4
4
  import os
5
- from datetime import datetime
6
5
  import struct
7
6
  from tqdm import tqdm
8
7
 
9
8
  import numpy as np
10
9
  import pydicom
11
10
  from pydicom.util.codify import code_file
11
+ from pydicom.tag import Tag
12
12
  import pydicom.config
13
13
  import vreg
14
14
 
15
-
15
+ from dbdicom.utils.pydicom_dataset import get_values, set_values
16
16
  import dbdicom.utils.image as image
17
- import dbdicom.utils.variables as variables
18
17
  from dbdicom.sop_classes import (
19
18
  xray_angiographic_image,
20
19
  ct_image,
@@ -50,15 +49,15 @@ SOPCLASSMODULE = {
50
49
  }
51
50
 
52
51
 
53
- def read_dataset(file):
52
+ # def read_dataset(file):
54
53
 
55
- try:
56
- ds = pydicom.dcmread(file)
57
- # ds = pydicom.dcmread(file, force=True) # more robust but hides corrupted data
58
- except Exception:
59
- raise FileNotFoundError('File not found')
54
+ # try:
55
+ # ds = pydicom.dcmread(file)
56
+ # # ds = pydicom.dcmread(file, force=True) # more robust but hides corrupted data
57
+ # except Exception:
58
+ # raise FileNotFoundError('File not found')
60
59
 
61
- return ds
60
+ # return ds
62
61
 
63
62
 
64
63
  def new_dataset(sop_class):
@@ -81,149 +80,6 @@ def new_dataset(sop_class):
81
80
  )
82
81
 
83
82
 
84
-
85
- def get_values(ds, tags):
86
- """Return a list of values for a dataset"""
87
-
88
- # https://pydicom.github.io/pydicom/stable/guides/element_value_types.html
89
- if np.isscalar(tags):
90
- return get_values(ds, [tags])[0]
91
-
92
- row = []
93
- for tag in tags:
94
- value = None
95
-
96
- # If the tag is provided as string
97
- if isinstance(tag, str):
98
- if hasattr(ds, tag):
99
- pydcm_value = ds[tag].value
100
- try:
101
- VR = pydicom.datadict.dictionary_VR(tag)
102
- except:
103
- VR = None
104
- value = to_set_type(pydcm_value, VR) # ELIMINATE THIS STEP - return pydicom datatypes
105
-
106
- # If the tag is a tuple of hexadecimal values
107
- else:
108
- if tag in ds:
109
- try:
110
- VR = pydicom.datadict.dictionary_VR(tag)
111
- except:
112
- VR = None
113
- value = to_set_type(ds[tag].value, VR)
114
-
115
- # If a tag is not present in the dataset, check if it can be derived
116
- if value is None:
117
- value = derive_data_element(ds, tag)
118
-
119
- row.append(value)
120
- return row
121
-
122
-
123
- def set_values(ds, tags, values, VR=None, coords=None):
124
-
125
- if np.isscalar(tags):
126
- tags = [tags]
127
- values = [values]
128
- VR = [VR]
129
- elif VR is None:
130
- VR = [None] * len(tags)
131
-
132
- if coords is not None:
133
- tags += list(coords.keys())
134
- values += list(coords.values())
135
-
136
- for i, tag in enumerate(tags):
137
-
138
- if values[i] is None:
139
- if isinstance(tag, str):
140
- if hasattr(ds, tag):
141
- del ds[tag]
142
- else: # hexadecimal tuple
143
- if tag in ds:
144
- del ds[tag]
145
-
146
- elif isinstance(tag, str):
147
- if hasattr(ds, tag):
148
- ds[tag].value = format_value(values[i], tag=tag)
149
- else:
150
- _add_new(ds, tag, values[i], VR=VR[i])
151
-
152
- else: # hexadecimal tuple
153
- if tag in ds:
154
- ds[tag].value = format_value(values[i], tag=tag)
155
- else:
156
- _add_new(ds, tag, values[i], VR=VR[i])
157
-
158
- #_set_derived_data_element(ds, tag, values[i])
159
-
160
- return ds
161
-
162
-
163
-
164
- def value(ds, tags):
165
- # Same as get_values but without VR lookup
166
-
167
- # https://pydicom.github.io/pydicom/stable/guides/element_value_types.html
168
- if np.isscalar(tags):
169
- return get_values(ds, [tags])[0]
170
-
171
- row = []
172
- for tag in tags:
173
- value = None
174
-
175
- # If the tag is provided as string
176
- if isinstance(tag, str):
177
-
178
- if hasattr(ds, tag):
179
- value = to_set_type(ds[tag].value)
180
-
181
- # If the tag is a tuple of hexadecimal values
182
- else:
183
- if tag in ds:
184
- value = to_set_type(ds[tag].value)
185
-
186
- # If a tag is not present in the dataset, check if it can be derived
187
- if value is None:
188
- value = derive_data_element(ds, tag)
189
-
190
- row.append(value)
191
- return row
192
-
193
-
194
- def set_value(ds, tags, values):
195
- # Same as set_values but without VR lookup
196
- # This excludes new private tags - set those using add_private()
197
- if np.isscalar(tags):
198
- tags = [tags]
199
- values = [values]
200
-
201
- for i, tag in enumerate(tags):
202
-
203
- if values[i] is None:
204
- if isinstance(tag, str):
205
- if hasattr(ds, tag):
206
- del ds[tag]
207
- else: # hexadecimal tuple
208
- if tag in ds:
209
- del ds[tag]
210
-
211
- elif isinstance(tag, str):
212
- if hasattr(ds, tag):
213
- ds[tag].value = check_value(values[i], tag)
214
- else:
215
- add_new(ds, tag, values[i])
216
-
217
- else: # hexadecimal tuple
218
- if tag in ds:
219
- ds[tag].value = check_value(values[i], tag)
220
- else:
221
- add_new(ds, tag, values[i])
222
-
223
- return ds
224
-
225
-
226
-
227
83
  def write(ds, file, status=None):
228
84
  # check if directory exists and create it if not
229
85
  dir = os.path.dirname(file)
@@ -268,150 +124,12 @@ def read_data(files, tags, path=None, images_only=False): # obsolete??
268
124
 
269
125
 
270
126
 
271
-
272
- def _add_new(ds, tag, value, VR='OW'):
273
- if not isinstance(tag, pydicom.tag.BaseTag):
274
- tag = pydicom.tag.Tag(tag)
275
- if not tag.is_private: # Add a new data element
276
- value_repr = pydicom.datadict.dictionary_VR(tag)
277
- if value_repr == 'US or SS':
278
- if value >= 0:
279
- value_repr = 'US'
280
- else:
281
- value_repr = 'SS'
282
- elif value_repr == 'OB or OW':
283
- value_repr = 'OW'
284
- ds.add_new(tag, value_repr, format_value(value, value_repr))
285
- else:
286
- if (tag.group, 0x0010) not in ds:
287
- ds.private_block(tag.group, 'dbdicom ' + str(tag.group), create=True)
288
- ds.add_new(tag, VR, format_value(value, VR))
289
-
290
-
291
- def add_new(ds, tag, value):
292
- if not isinstance(tag, pydicom.tag.BaseTag):
293
- tag = pydicom.tag.Tag(tag)
294
- if tag.is_private:
295
- raise ValueError("if you want to add a private data element, use "
296
- "dataset.add_private()")
297
- # Add a new data element
298
- value_repr = pydicom.datadict.dictionary_VR(tag)
299
- if value_repr == 'US or SS':
300
- if value >= 0:
301
- value_repr = 'US'
302
- else:
303
- value_repr = 'SS'
304
- elif value_repr == 'OB or OW':
305
- value_repr = 'OW'
306
- ds.add_new(tag, value_repr, format_value(value, value_repr))
307
-
308
-
309
-
310
- def add_private(ds, tag, value, VR):
311
- if not isinstance(tag, pydicom.tag.BaseTag):
312
- tag = pydicom.tag.Tag(tag)
313
- if (tag.group, 0x0010) not in ds:
314
- ds.private_block(tag.group, 'dbdicom ' + str(tag.group), create=True)
315
- ds.add_new(tag, VR, format_value(value, VR))
316
-
317
-
318
- def derive_data_element(ds, tag):
319
- """Tags that are not required but can be derived from other required tags"""
320
-
321
- if tag == 'SliceLocation' or tag == (0x0020, 0x1041):
322
- if 'ImageOrientationPatient' in ds and 'ImagePositionPatient' in ds:
323
- return image.slice_location(
324
- ds['ImageOrientationPatient'].value,
325
- ds['ImagePositionPatient'].value,
326
- )
327
- # To be extended ad hoc with other tags that can be derived
328
-
329
-
330
-
331
- def format_value(value, VR=None, tag=None):
332
-
333
- # If the change below is made (TM, DA, DT) then this needs to
334
- # convert those to string before setting
335
-
336
- # Slow - dictionary lookup for every value write
337
-
338
- if VR is None:
339
- VR = pydicom.datadict.dictionary_VR(tag)
340
-
341
- if VR == 'LO':
342
- if len(value) > 64:
343
- return value[-64:]
344
- #return value[:64]
345
- if VR == 'TM':
346
- return variables.seconds_to_str(value)
347
-
348
- return value
349
-
350
-
351
- def check_value(value, tag):
352
-
353
- # If the change below is made (TM, DA, DT) then this needs to
354
- # convert those to string before setting
355
-
356
- LO = [
357
- 'SeriesDescription',
358
- 'StudyDescription',
359
- ]
360
- TM = [
361
- 'AcquisitionTime',
362
- ]
363
-
364
- if tag in LO:
365
- if len(value) > 64:
366
- return value[-64:]
367
- if tag in TM:
368
- return variables.seconds_to_str(value)
127
+ # def new_uid(n=None):
369
128
 
370
- return value
371
-
372
-
373
- def to_set_type(value, VR=None):
374
- """
375
- Convert pydicom datatypes to the python datatypes used to set the parameter.
376
- """
377
- # Not a good idea to modify pydicom set/get values. confusing and requires extra VR lookups
378
-
379
- if VR == 'TM':
380
- # pydicom sometimes returns string values for TM data types
381
- if isinstance(value, str):
382
- return variables.str_to_seconds(value)
383
-
384
- if value.__class__.__name__ == 'MultiValue':
385
- return [to_set_type(v, VR) for v in value]
386
- if value.__class__.__name__ == 'PersonName':
387
- return str(value)
388
- if value.__class__.__name__ == 'Sequence':
389
- return [ds for ds in value]
390
- if value.__class__.__name__ == 'TM':
391
- return variables.time_to_seconds(value) # return datetime.time
392
- if value.__class__.__name__ == 'UID':
393
- return str(value)
394
- if value.__class__.__name__ == 'IS':
395
- return int(value)
396
- if value.__class__.__name__ == 'DT':
397
- return variables.datetime_to_str(value) # return datetime.datetime
398
- if value.__class__.__name__ == 'DA': # return datetime.date
399
- return variables.date_to_str(value)
400
- if value.__class__.__name__ == 'DSfloat':
401
- return float(value)
402
- if value.__class__.__name__ == 'DSdecimal':
403
- return int(value)
404
-
405
- return value
406
-
407
-
408
- def new_uid(n=None):
409
-
410
- if n is None:
411
- return pydicom.uid.generate_uid()
412
- else:
413
- return [pydicom.uid.generate_uid() for _ in range(n)]
414
-
129
+ # if n is None:
130
+ # return pydicom.uid.generate_uid()
131
+ # else:
132
+ # return [pydicom.uid.generate_uid() for _ in range(n)]
415
133
 
416
134
 
417
135
 
@@ -624,6 +342,15 @@ def set_pixel_data(ds, array):
624
342
  def volume(ds):
625
343
  return vreg.volume(pixel_data(ds), affine(ds))
626
344
 
345
+
346
+
347
+ def is_valid_dicom_tag(value):
348
+ try:
349
+ tag = Tag(value)
350
+ return pydicom.datadict.dictionary_keyword(tag) != ''
351
+ except Exception:
352
+ return False
353
+
627
354
  def set_volume(ds, volume:vreg.Volume3D):
628
355
  if volume is None:
629
356
  raise ValueError('The volume cannot be set to an empty value.')
@@ -645,15 +372,16 @@ def set_volume(ds, volume:vreg.Volume3D):
645
372
  # All other dimensions should have size 1
646
373
  coords = volume.coords.reshape((volume.coords.shape[0], -1))
647
374
  for i, d in enumerate(volume.dims):
648
- try:
649
- set_values(ds, d, coords[i,0])
650
- except KeyError:
375
+ if not is_valid_dicom_tag(d):
651
376
  raise ValueError(
652
377
  "Cannot write volume to DICOM. "
653
378
  f"Volume dimension {d} is not a recognized DICOM data-element. "
654
- f"Use Volume3D.set_dims() with proper DICOM keywords "
655
- "or (group, element) tags to change the dimensions."
379
+ f"Use Volume3D.set_dims() with proper DICOM "
380
+ "tags to change the dimensions."
656
381
  )
382
+ else:
383
+ set_values(ds, d, coords[i,0])
384
+
657
385
 
658
386
 
659
387
  def image_type(ds):