dbdicom 0.2.1__py3-none-any.whl → 0.2.4__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.

Files changed (50) hide show
  1. dbdicom/__init__.py +4 -3
  2. dbdicom/create.py +34 -97
  3. dbdicom/dro.py +174 -0
  4. dbdicom/ds/dataset.py +31 -4
  5. dbdicom/ds/types/mr_image.py +18 -7
  6. dbdicom/extensions/__init__.py +9 -0
  7. dbdicom/{wrappers → extensions}/dipy.py +191 -205
  8. dbdicom/extensions/elastix.py +503 -0
  9. dbdicom/extensions/matplotlib.py +107 -0
  10. dbdicom/extensions/numpy.py +271 -0
  11. dbdicom/{wrappers → extensions}/scipy.py +130 -31
  12. dbdicom/{wrappers → extensions}/skimage.py +1 -1
  13. dbdicom/extensions/sklearn.py +243 -0
  14. dbdicom/extensions/vreg.py +1390 -0
  15. dbdicom/external/dcm4che/bin/emf2sf +57 -57
  16. dbdicom/manager.py +70 -36
  17. dbdicom/pipelines.py +66 -0
  18. dbdicom/record.py +266 -43
  19. dbdicom/types/instance.py +54 -19
  20. dbdicom/types/series.py +2183 -412
  21. dbdicom/utils/image.py +256 -48
  22. dbdicom-0.2.4.dist-info/METADATA +89 -0
  23. {dbdicom-0.2.1.dist-info → dbdicom-0.2.4.dist-info}/RECORD +26 -41
  24. {dbdicom-0.2.1.dist-info → dbdicom-0.2.4.dist-info}/WHEEL +1 -1
  25. dbdicom/external/__pycache__/__init__.cpython-310.pyc +0 -0
  26. dbdicom/external/__pycache__/__init__.cpython-37.pyc +0 -0
  27. dbdicom/external/dcm4che/__pycache__/__init__.cpython-310.pyc +0 -0
  28. dbdicom/external/dcm4che/__pycache__/__init__.cpython-37.pyc +0 -0
  29. dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-310.pyc +0 -0
  30. dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-37.pyc +0 -0
  31. dbdicom/external/dcm4che/lib/linux-x86/libclib_jiio.so +0 -0
  32. dbdicom/external/dcm4che/lib/linux-x86-64/libclib_jiio.so +0 -0
  33. dbdicom/external/dcm4che/lib/linux-x86-64/libopencv_java.so +0 -0
  34. dbdicom/external/dcm4che/lib/solaris-sparc/libclib_jiio.so +0 -0
  35. dbdicom/external/dcm4che/lib/solaris-sparc/libclib_jiio_vis.so +0 -0
  36. dbdicom/external/dcm4che/lib/solaris-sparc/libclib_jiio_vis2.so +0 -0
  37. dbdicom/external/dcm4che/lib/solaris-sparcv9/libclib_jiio.so +0 -0
  38. dbdicom/external/dcm4che/lib/solaris-sparcv9/libclib_jiio_vis.so +0 -0
  39. dbdicom/external/dcm4che/lib/solaris-sparcv9/libclib_jiio_vis2.so +0 -0
  40. dbdicom/external/dcm4che/lib/solaris-x86/libclib_jiio.so +0 -0
  41. dbdicom/external/dcm4che/lib/solaris-x86-64/libclib_jiio.so +0 -0
  42. dbdicom/utils/vreg.py +0 -2626
  43. dbdicom/wrappers/__init__.py +0 -7
  44. dbdicom/wrappers/elastix.py +0 -855
  45. dbdicom/wrappers/numpy.py +0 -119
  46. dbdicom/wrappers/sklearn.py +0 -151
  47. dbdicom/wrappers/vreg.py +0 -273
  48. dbdicom-0.2.1.dist-info/METADATA +0 -276
  49. {dbdicom-0.2.1.dist-info → dbdicom-0.2.4.dist-info}/LICENSE +0 -0
  50. {dbdicom-0.2.1.dist-info → dbdicom-0.2.4.dist-info}/top_level.txt +0 -0
dbdicom/__init__.py CHANGED
@@ -1,13 +1,13 @@
1
1
 
2
2
  from .create import (
3
3
  database,
4
- database_hollywood,
5
4
  patient,
6
5
  study,
7
6
  series,
8
7
  as_series,
9
8
  zeros,
10
9
  ones,
10
+ empty_series,
11
11
  )
12
12
  from .record import (
13
13
  copy_to,
@@ -23,5 +23,6 @@ from .types.database import Database
23
23
  from .types.patient import Patient
24
24
  from .types.study import Study
25
25
  from .types.series import Series
26
-
27
- from .utils import image
26
+ from .utils import image
27
+ from . import extensions
28
+ from . import dro
dbdicom/create.py CHANGED
@@ -6,7 +6,7 @@ from dbdicom.manager import Manager
6
6
  from dbdicom.types.database import Database
7
7
  from dbdicom.types.patient import Patient
8
8
  from dbdicom.types.study import Study
9
- from dbdicom.types.series import Series
9
+ from dbdicom.types.series import Series, _coords_size, _grid_to_coords
10
10
  from dbdicom.types.instance import Instance
11
11
 
12
12
 
@@ -270,6 +270,7 @@ def series(dtype='mri', in_study:Study=None, in_database:Database=None, **kwargs
270
270
  else:
271
271
  if in_database is None:
272
272
  _database = database()
273
+ _database.mute()
273
274
  else:
274
275
  _database = in_database
275
276
  patient = _database.new_patient()
@@ -281,73 +282,14 @@ def series(dtype='mri', in_study:Study=None, in_database:Database=None, **kwargs
281
282
 
282
283
 
283
284
 
284
- def database_hollywood()->Database:
285
- """Create an empty toy database for demonstration purposes.
286
285
 
287
- Returns:
288
- Database: Database with two patients, two studies per patient and two empty series per study.
289
-
290
- See Also:
291
- :func:`~database`
292
-
293
- Example:
294
- >>> database = db.database_hollywood()
295
- >>> database.print()
296
- ---------- DATABASE --------------
297
- Location: In memory
298
- Patient James Bond
299
- Study MRI [19821201]
300
- Series 001 [Localizer]
301
- Nr of instances: 0
302
- Series 002 [T2w]
303
- Nr of instances: 0
304
- Study Xray [19821205]
305
- Series 001 [Chest]
306
- Nr of instances: 0
307
- Series 002 [Head]
308
- Nr of instances: 0
309
- Patient Scarface
310
- Study MRI [19850105]
311
- Series 001 [Localizer]
312
- Nr of instances: 0
313
- Series 002 [T2w]
314
- Nr of instances: 0
315
- Study Xray [19850106]
316
- Series 001 [Chest]
317
- Nr of instances: 0
318
- Series 002 [Head]
319
- Nr of instances: 0
320
- ---------------------------------
321
- """
322
- hollywood = database()
323
-
324
- james_bond = hollywood.new_patient(PatientName='James Bond')
325
- james_bond_mri = james_bond.new_study(StudyDescription='MRI', StudyDate='19821201')
326
- james_bond_mri_localizer = james_bond_mri.new_series(SeriesDescription='Localizer')
327
- james_bond_mri_T2w = james_bond_mri.new_series(SeriesDescription='T2w')
328
- james_bond_xray = james_bond.new_study(StudyDescription='Xray', StudyDate='19821205')
329
- james_bond_xray_chest = james_bond_xray.new_series(SeriesDescription='Chest')
330
- james_bond_xray_head = james_bond_xray.new_series(SeriesDescription='Head')
331
-
332
- scarface = hollywood.new_patient(PatientName='Scarface')
333
- scarface_mri = scarface.new_study(StudyDescription='MRI', StudyDate='19850105')
334
- scarface_mri_localizer = scarface_mri.new_series(SeriesDescription='Localizer')
335
- scarface_mri_T2w = scarface_mri.new_series(SeriesDescription='T2w')
336
- scarface_xray = scarface.new_study(StudyDescription='Xray', StudyDate='19850106')
337
- scarface_xray_chest = scarface_xray.new_series(SeriesDescription='Chest')
338
- scarface_xray_head = scarface_xray.new_series(SeriesDescription='Head')
339
-
340
- return hollywood
341
-
342
-
343
-
344
-
345
- def as_series(array:np.ndarray, coords:dict=None, dtype='mri', in_study:Study=None, in_database:Database=None, **kwargs)->Series:
286
+ def as_series(array:np.ndarray, coords:dict=None, gridcoords:dict=None, dtype='mri', in_study:Study=None, in_database:Database=None, **kwargs)->Series:
346
287
  """Create a DICOM series from a numpy array.
347
288
 
348
289
  Args:
349
290
  array (np.ndarray): numpy.ndarray with image data
350
- coords (dict, optional): Dictionary with coordinate labels and values. For 3- or 4-dimensional arrays this is optional but for arrays with more than 4 dimensions this is required. The coordinate values can be one-dimensions for regularly gridded data, or n-dimensional for irregularly gridded data.
291
+ coords (dict, optional): Dictionary with coordinate labels and values. For 3- or 4-dimensional arrays this is optional but for arrays with more than 4 dimensions either *coords* or *gridcoords* are required.
292
+ gridcoords (dict, optional): regularly gridded coordinates can also be provided as a coordinate grid.
351
293
  dtype (str, optional): The type of the series to create. Defaults to 'mri'.
352
294
  in_study (Study, optional): If provided, the series is created in this study. Defaults to None.
353
295
  in_database (Database, optional): If provided, the series is created in this database. Defaults to None.
@@ -404,23 +346,37 @@ def as_series(array:np.ndarray, coords:dict=None, dtype='mri', in_study:Study=No
404
346
  """
405
347
  shape = array.shape
406
348
  if coords is None:
407
- if len(shape) > 4:
408
- msg = 'With more than 4 dimensions, the coordinates argument is required'
409
- raise ValueError(msg)
410
- else:
411
- coords = {}
349
+ if gridcoords is None:
350
+ if len(shape) > 4:
351
+ msg = 'With more than 4 dimensions, the coords argument is required.'
352
+ raise ValueError(msg)
353
+ gridcoords = {}
354
+ if len(shape) == 2:
355
+ gridcoords['InstanceNumber'] = np.array([1])
412
356
  if len(shape) > 2:
413
- coords['SliceLocation'] = np.arange(array.shape[2])
357
+ gridcoords['SliceLocation'] = np.arange(shape[2])
414
358
  if len(shape) > 3:
415
- coords['AcquisitionTime'] = np.arange(array.shape[3])
359
+ gridcoords['AcquisitionTime'] = np.arange(shape[3])
360
+ if gridcoords is not None:
361
+ coords = _grid_to_coords(gridcoords)
362
+ sery = series(dtype=dtype, in_study=in_study, in_database=in_database, **kwargs)
363
+ sery.expand(coords)
364
+ sery.set_pixel_values(array, dims=tuple(coords))
365
+ return sery
366
+
367
+
368
+ def empty_series(coords:dict=None, gridcoords:dict=None, dtype='mri', in_study:Study=None, in_database:Database=None, **kwargs)->Series:
369
+
370
+ if gridcoords is not None:
371
+ coords = _grid_to_coords(gridcoords)
416
372
  sery = series(dtype=dtype, in_study=in_study, in_database=in_database, **kwargs)
417
- sery.mute()
418
- sery.set_ndarray(array, coords=coords)
419
- sery.unmute()
373
+ if coords is None:
374
+ return sery
375
+ sery.expand(coords)
420
376
  return sery
421
377
 
422
378
 
423
- def zeros(shape:tuple, coords:dict=None, **kwargs) -> Series:
379
+ def zeros(shape:tuple, coords:dict=None, gridcoords:dict=None, **kwargs) -> Series:
424
380
  """Create a DICOM series populated with zeros.
425
381
 
426
382
  This is a convenience wrapper providing a numpy-like interface for :func:`~as_series`.
@@ -456,21 +412,12 @@ def zeros(shape:tuple, coords:dict=None, **kwargs) -> Series:
456
412
  >>> array = np.zeros((128, 128, 2, 3))
457
413
  >>> zeros = db.as_series(array)
458
414
  """
459
- if coords is None:
460
- if len(shape) > 4:
461
- msg = 'With more than 4 dimensions, the coordinates argument is required'
462
- raise ValueError(msg)
463
- else:
464
- coords = {}
465
- if len(shape) > 2:
466
- coords['SliceLocation'] = np.arange(shape[2])
467
- if len(shape) > 3:
468
- coords['AcquisitionTime'] = np.arange(shape[3])
415
+
469
416
  array = np.zeros(shape, dtype=np.float32)
470
- return as_series(array, coords=coords, **kwargs)
417
+ return as_series(array, coords=coords, gridcoords=gridcoords, **kwargs)
471
418
 
472
419
 
473
- def ones(shape:tuple, coords:dict=None, **kwargs) -> Series:
420
+ def ones(shape:tuple, coords:dict=None, gridcoords:dict=None, **kwargs) -> Series:
474
421
  """Create a DICOM series populated with ones.
475
422
 
476
423
  This is a convenience wrapper providing a numpy-like interface for :func:`~as_series`.
@@ -506,15 +453,5 @@ def ones(shape:tuple, coords:dict=None, **kwargs) -> Series:
506
453
  >>> array = np.ones((128, 128, 2, 3))
507
454
  >>> zeros = db.as_series(array)
508
455
  """
509
- if coords is None:
510
- if len(shape) > 4:
511
- msg = 'With more than 4 dimensions, the coordinates argument is required'
512
- raise ValueError(msg)
513
- else:
514
- coords = {}
515
- if len(shape) > 2:
516
- coords['SliceLocation'] = np.arange(shape[2])
517
- if len(shape) > 3:
518
- coords['AcquisitionTime'] = np.arange(shape[3])
519
456
  array = np.ones(shape, dtype=np.float32)
520
- return as_series(array, coords=coords, **kwargs)
457
+ return as_series(array, coords=coords, gridcoords=gridcoords, **kwargs)
dbdicom/dro.py ADDED
@@ -0,0 +1,174 @@
1
+ # Importing annotations to handle or sign in import type hints
2
+ from __future__ import annotations
3
+
4
+ import numpy as np
5
+ import dbdicom as db
6
+ from dbdicom.types.database import Database
7
+ from dbdicom.types.series import Series
8
+ from dbdicom.utils import image
9
+
10
+
11
+ def T1_mapping_vFATR(spacing = (15, 15, 20), fov = (300, 250, 120), T1min = 600, S0min = 100, vFA = [2.0, 20.0], vTR = [5.0,15.0])->Series:
12
+ """Synthetic T1-mapping data with variable TR and FA
13
+
14
+ Args:
15
+ spacing (tuple, optional): x, y, z pixel spacing in mm. Defaults to (1.5, 1.5, 2.0).
16
+ fov (tuple, optional): x, y, z field of view in mm. Defaults to (300, 250, 120).
17
+ T1min (int, optional): smallest T1 in msec. Defaults to 600.
18
+ S0min (int, optional): smallest S0 in a.u. Defaults to 100.
19
+ vFA (list, optional): variable flip angle values in degrees. Defaults to [2.0, 5.0, 10.0, 15.0, 20.0].
20
+ vTR (list, optional): variable repetition time values in msec. Defaults to [2.0, 3.0, 4.0, 5.0, 10.0, 15.0].
21
+
22
+ Returns:
23
+ dbdicom.Series: A series with appropriate array and header data.
24
+ """
25
+ ellipsoid = image.ellipsoid(fov[0]/2, fov[1]/2, fov[2]/2, spacing=spacing, levelset=True)
26
+ ellipsoid = 1 + ellipsoid - np.amin(ellipsoid)
27
+ T1 = T1min*ellipsoid
28
+ S0 = S0min*ellipsoid
29
+ array = np.empty((T1.shape[0], T1.shape[1], T1.shape[2], len(vFA), len(vTR)))
30
+ for j, TR in enumerate(vTR):
31
+ Ej = np.exp(-TR/T1)
32
+ for i, FA in enumerate(vFA):
33
+ ci = np.cos(FA*np.pi/180)
34
+ array[:,:,:,i,j] = S0 * (1-Ej) / (1-ci*Ej)
35
+
36
+ coords = {
37
+ 'SliceLocation': spacing[2]*np.arange(array.shape[2]),
38
+ 'FlipAngle': np.array(vFA),
39
+ 'RepetitionTime': np.array(vTR),
40
+ }
41
+ v0, v1 = np.amin(array), np.amax(array)
42
+ series = db.as_series(array, gridcoords=coords, PixelSpacing=[spacing[1],spacing[0]], WindowWidth=v1-v0, WindowCenter=(v0+v1)/2)
43
+ series.patient().PatientName = 'Ellipsoid'
44
+ series.study().StudyDescription = 'Synthetic'
45
+ series.SeriesDescription = 'T1 mapping variable TR and FA'
46
+
47
+ return series
48
+
49
+
50
+ def ellipsoid(a, b, c, spacing=(1., 1., 1.), levelset=False)->Series:
51
+ """
52
+ Generates ellipsoid with semimajor axes aligned with grid dimensions
53
+ on grid with specified `spacing`.
54
+
55
+ Args:
56
+ a (float): Length of semimajor axis aligned with x-axis.
57
+ b (float): Length of semimajor axis aligned with y-axis.
58
+ c (float): Length of semimajor axis aligned with z-axis.
59
+ spacing (tuple of floats, length 3): Spacing in (x, y, z) spatial dimensions. Defaults to (1,1,1)
60
+ levelset (bool): If True, returns the level set for this ellipsoid (signed level set about zero, with positive denoting interior) as np.float64. False returns a binarized version of said level set. Defaults to False.
61
+
62
+ Returns:
63
+ dbdicom.Series: A series with appropriate array and header data.
64
+
65
+ Note:
66
+ The interface and the array generation is taken directly from skimage but the core function is copied into dbdicom utilities to avoid bringing in skimage as an essential dependency.
67
+ """
68
+ arr = image.ellipsoid(a, b, c, spacing=spacing, levelset=levelset)
69
+ coords = {'SliceLocation': spacing[2]*np.arange(arr.shape[2])}
70
+ v0, v1 = np.amin(arr), np.amax(arr)
71
+ series = db.as_series(arr, gridcoords=coords, PixelSpacing=[spacing[1],spacing[0]], WindowWidth=v1-v0, WindowCenter=(v0+v1)/2)
72
+ affine = np.array(
73
+ [[spacing[1], 0., 0., 0.],
74
+ [0., spacing[0], 0., 0.],
75
+ [0., 0., spacing[2], 0.],
76
+ [0., 0., 0., 1.]]
77
+ )
78
+ series.set_affine(affine)
79
+ series.patient().PatientName = 'Ellipsoid'
80
+ series.study().StudyDescription = 'Synthetic'
81
+ series.SeriesDescription = 'Levelset ellipsoid'
82
+ return series
83
+
84
+
85
+ def double_ellipsoid(a, b, c, spacing=(1., 1., 1.), levelset=False)->Series:
86
+ """
87
+ Generates a double ellipsoid with semimajor axes aligned with grid dimensions
88
+ on grid with specified `spacing`.
89
+
90
+ Args:
91
+ a (float): Length of semimajor axis aligned with x-axis.
92
+ b (float): Length of semimajor axis aligned with y-axis.
93
+ c (float): Length of semimajor axis aligned with z-axis.
94
+ spacing (tuple of floats, length 3): Spacing in (x, y, z) spatial dimensions. Defaults to (1,1,1)
95
+ levelset (bool): If True, returns the level set for this ellipsoid (signed level set about zero, with positive denoting interior) as np.float64. False returns a binarized version of said level set. Defaults to False.
96
+
97
+ Returns:
98
+ dbdicom.Series: A series with appropriate array and header data.
99
+
100
+ Note:
101
+ The interface and the array generation is taken directly from skimage, but the core function is copied into dbdicom utilities to avoid bringing in skimage as an essential dependency.
102
+ """
103
+ arr = image.ellipsoid(a, b, c, spacing=spacing, levelset=levelset)
104
+ coords = {'SliceLocation': spacing[2]*np.arange(arr.shape[2])}
105
+ arr = np.concatenate((arr[:-1, ...], arr[2:, ...]), axis=0)
106
+ v0, v1 = np.amin(arr), np.amax(arr)
107
+ series = db.as_series(arr, gridcoords=coords, PixelSpacing=[spacing[1],spacing[0]], WindowWidth=v1-v0, WindowCenter=(v0+v1)/2)
108
+ series.patient().PatientName = 'Ellipsoid'
109
+ series.study().StudyDescription = 'Synthetic'
110
+ series.SeriesDescription = 'Levelset ellipsoid'
111
+ return series
112
+
113
+
114
+ def database_hollywood()->Database:
115
+ """Create an empty toy database for demonstration purposes.
116
+
117
+ Returns:
118
+ Database: Database with two patients, two studies per patient and two empty series per study.
119
+
120
+ See Also:
121
+ :func:`~database`
122
+
123
+ Example:
124
+ >>> database = db.dro.database_hollywood()
125
+ >>> database.print()
126
+ ---------- DATABASE --------------
127
+ Location: In memory
128
+ Patient James Bond
129
+ Study MRI [19821201]
130
+ Series 001 [Localizer]
131
+ Nr of instances: 0
132
+ Series 002 [T2w]
133
+ Nr of instances: 0
134
+ Study Xray [19821205]
135
+ Series 001 [Chest]
136
+ Nr of instances: 0
137
+ Series 002 [Head]
138
+ Nr of instances: 0
139
+ Patient Scarface
140
+ Study MRI [19850105]
141
+ Series 001 [Localizer]
142
+ Nr of instances: 0
143
+ Series 002 [T2w]
144
+ Nr of instances: 0
145
+ Study Xray [19850106]
146
+ Series 001 [Chest]
147
+ Nr of instances: 0
148
+ Series 002 [Head]
149
+ Nr of instances: 0
150
+ ---------------------------------
151
+ """
152
+ hollywood = db.database()
153
+ hollywood.mute()
154
+
155
+ james_bond = hollywood.new_patient(PatientName='James Bond')
156
+ james_bond_mri = james_bond.new_study(StudyDescription='MRI', StudyDate='19821201')
157
+ james_bond_mri_localizer = james_bond_mri.new_series(SeriesDescription='Localizer')
158
+ james_bond_mri_T2w = james_bond_mri.new_series(SeriesDescription='T2w')
159
+ james_bond_xray = james_bond.new_study(StudyDescription='Xray', StudyDate='19821205')
160
+ james_bond_xray_chest = james_bond_xray.new_series(SeriesDescription='Chest')
161
+ james_bond_xray_head = james_bond_xray.new_series(SeriesDescription='Head')
162
+
163
+ scarface = hollywood.new_patient(PatientName='Scarface')
164
+ scarface_mri = scarface.new_study(StudyDescription='MRI', StudyDate='19850105')
165
+ scarface_mri_localizer = scarface_mri.new_series(SeriesDescription='Localizer')
166
+ scarface_mri_T2w = scarface_mri.new_series(SeriesDescription='T2w')
167
+ scarface_xray = scarface.new_study(StudyDescription='Xray', StudyDate='19850106')
168
+ scarface_xray_chest = scarface_xray.new_series(SeriesDescription='Chest')
169
+ scarface_xray_head = scarface_xray.new_series(SeriesDescription='Head')
170
+
171
+ return hollywood
172
+
173
+ if __name__ == '__main__':
174
+ T1_mapping_vFATR()
dbdicom/ds/dataset.py CHANGED
@@ -306,9 +306,21 @@ def set_values(ds, tags, values, VR=None):
306
306
  ds[tag].value = format_value(values[i], tag=tag)
307
307
  else:
308
308
  _add_new(ds, tag, values[i], VR=VR[i])
309
+
310
+ #_set_derived_data_element(ds, tag, values[i])
311
+
309
312
  return ds
310
313
 
311
314
 
315
+ # def _set_derived_data_element(ds, tag, value):
316
+ # """Set any tags that are need to change as well"""
317
+
318
+ # if tag == 'SliceLocation' or tag == (0x0020, 0x1041):
319
+ # if value is not None:
320
+ # loc = ds['ImageOrientationPatient'].value
321
+ # ds['ImagePositionPatient'].value = image.image_position_from_slice_location(value, loc)
322
+
323
+
312
324
  def _add_new(ds, tag, value, VR='OW'):
313
325
  if not isinstance(tag, pydicom.tag.BaseTag):
314
326
  tag = pydicom.tag.Tag(tag)
@@ -324,10 +336,15 @@ def _add_new(ds, tag, value, VR='OW'):
324
336
  ds.add_new(tag, value_repr, format_value(value, value_repr))
325
337
  else:
326
338
  if (tag.group, 0x0010) not in ds:
327
- ds.private_block(tag.group, 'Wezel ' + str(tag.group), create=True)
339
+ ds.private_block(tag.group, 'dbdicom ' + str(tag.group), create=True)
328
340
  ds.add_new(tag, VR, format_value(value, VR))
329
341
 
330
342
 
343
+
344
+
345
+
346
+
347
+
331
348
  def get_values(ds, tags):
332
349
  """Return a list of values for a dataset"""
333
350
 
@@ -347,12 +364,20 @@ def get_values(ds, tags):
347
364
  value = getattr(ds, 'get_attribute_' + tag)()
348
365
  else:
349
366
  pydcm_value = ds[tag].value
350
- value = to_set_type(pydcm_value, pydicom.datadict.dictionary_VR(tag)) # ELIMINATE THIS STEP - return pydicom datatypes
367
+ try:
368
+ VR = pydicom.datadict.dictionary_VR(tag)
369
+ except:
370
+ VR = None
371
+ value = to_set_type(pydcm_value, VR) # ELIMINATE THIS STEP - return pydicom datatypes
351
372
 
352
373
  # If the tag is a tuple of hexadecimal values
353
374
  else:
354
375
  if tag in ds:
355
- value = to_set_type(ds[tag].value, pydicom.datadict.dictionary_VR(tag))
376
+ try:
377
+ VR = pydicom.datadict.dictionary_VR(tag)
378
+ except:
379
+ VR = None
380
+ value = to_set_type(ds[tag].value, VR)
356
381
 
357
382
  # If a tag is not present in the dataset, check if it can be derived
358
383
  if value is None:
@@ -374,6 +399,7 @@ def derive_data_element(ds, tag):
374
399
  # To be extended ad hoc with other tags that can be derived
375
400
 
376
401
 
402
+
377
403
  def format_value(value, VR=None, tag=None):
378
404
 
379
405
  # If the change below is made (TM, DA, DT) then this needs to
@@ -437,6 +463,7 @@ def new_uid(n=None):
437
463
  return [pydicom.uid.generate_uid() for _ in range(n)]
438
464
 
439
465
 
466
+ # Obsolete - replaced by instance.affine()
440
467
  def get_affine_matrix(ds):
441
468
  """Affine transformation matrix for a DICOM image"""
442
469
 
@@ -444,7 +471,6 @@ def get_affine_matrix(ds):
444
471
  # if slice_spacing is None:
445
472
  # slice_spacing = get_values(ds, 'SliceThickness')
446
473
  slice_spacing = get_values(ds, 'SliceThickness')
447
-
448
474
  return image.affine_matrix(
449
475
  get_values(ds, 'ImageOrientationPatient'),
450
476
  get_values(ds, 'ImagePositionPatient'),
@@ -452,6 +478,7 @@ def get_affine_matrix(ds):
452
478
  slice_spacing)
453
479
 
454
480
 
481
+ # Obsolete - replaced by instance.set_affine()
455
482
  def set_affine_matrix(ds, affine):
456
483
  v = image.dismantle_affine_matrix(affine)
457
484
  set_values(ds, 'PixelSpacing', v['PixelSpacing'])
@@ -126,11 +126,11 @@ def rider(ds): # required only - check
126
126
  ds.SeriesNumber = '14'
127
127
  ds.AcquisitionNumber = '1'
128
128
  ds.InstanceNumber = '1'
129
- ds.ImagePositionPatient = [75.561665058136, -163.6216506958, 118.50172901154]
130
- ds.ImageOrientationPatient = [0, 1, 0, 0, 0, -1]
129
+ ds.ImagePositionPatient = [0, 0, 0]
130
+ ds.ImageOrientationPatient = [1, 0, 0, 0, 1, 0]
131
131
  ds.FrameOfReferenceUID = '1.3.6.1.4.1.9328.50.16.22344679587635360510174487884943834158'
132
132
  ds.PositionReferenceIndicator = ''
133
- ds.SliceLocation = '75.561665058136'
133
+ ds.SliceLocation = '0.0'
134
134
  ds.SamplesPerPixel = 1
135
135
  ds.PhotometricInterpretation = 'MONOCHROME2'
136
136
  ds.Rows = 64
@@ -156,7 +156,8 @@ def rider(ds): # required only - check
156
156
  ds.RequestAttributesSequence = Sequence()
157
157
  ds.RequestedProcedureID = '5133240'
158
158
  ds.StorageMediaFileSetUID = '1.3.6.1.4.1.9328.50.16.162890465625511526068665093825399871205'
159
- ds.PixelData = np.arange(ds.Rows*ds.Columns, dtype=np.uint16)*ds.LargestImagePixelValue/(ds.Rows*ds.Columns)
159
+ pixel_values = np.arange(ds.Rows*ds.Columns)*ds.LargestImagePixelValue/(ds.Rows*ds.Columns)
160
+ ds.PixelData = pixel_values.astype(np.uint16).tobytes()
160
161
 
161
162
  return ds
162
163
 
@@ -190,15 +191,25 @@ def set_pixel_array(ds, array):
190
191
  del ds[0x2005, 0x100E] # Delete 'Philips Rescale Slope'
191
192
  if (0x2005, 0x100D) in ds:
192
193
  del ds[0x2005, 0x100D]
193
-
194
+
194
195
  # clipping may slow down a lot
195
196
  array = image.clip(array.astype(np.float32))
196
197
  array, slope, intercept = image.scale_to_range(array, ds.BitsAllocated)
197
198
  array = np.transpose(array)
198
199
 
199
200
  ds.PixelRepresentation = 0
200
- ds.set_values('SmallestImagePixelValue', int(0))
201
- ds.set_values('LargestImagePixelValue', int(2**ds.BitsAllocated - 1))
201
+
202
+ # Does this need setting? Optional and should not be used like this anyway.
203
+ # Prob
204
+ # 11 june 2016: commented this out it produced busg in some cases due to US vs SS confusion
205
+ # vr = ds.data_element('SmallestImagePixelValue').VR
206
+ # if vr =='US':
207
+ # ds.set_values('SmallestImagePixelValue', int(0))
208
+ # ds.set_values('LargestImagePixelValue', int(2**ds.BitsAllocated - 1))
209
+ # else:
210
+ # ds.set_values('SmallestImagePixelValue', int(-2**(ds.BitsAllocated - 1)))
211
+ # ds.set_values('LargestImagePixelValue', int(2**(ds.BitsAllocated - 1)-1))
212
+
202
213
  ds.RescaleSlope = 1 / slope
203
214
  ds.RescaleIntercept = - intercept / slope
204
215
  # ds.WindowCenter = (maximum + minimum) / 2
@@ -0,0 +1,9 @@
1
+ from . import (
2
+ dipy,
3
+ elastix,
4
+ numpy,
5
+ scipy,
6
+ skimage,
7
+ sklearn,
8
+ matplotlib,
9
+ )