dbdicom 0.2.6__py3-none-any.whl → 0.3.0__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 (52) hide show
  1. dbdicom/__init__.py +1 -28
  2. dbdicom/api.py +267 -0
  3. dbdicom/const.py +144 -0
  4. dbdicom/dataset.py +752 -0
  5. dbdicom/dbd.py +719 -0
  6. dbdicom/external/__pycache__/__init__.cpython-311.pyc +0 -0
  7. dbdicom/external/dcm4che/__pycache__/__init__.cpython-311.pyc +0 -0
  8. dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-311.pyc +0 -0
  9. dbdicom/register.py +527 -0
  10. dbdicom/{ds/types → sop_classes}/ct_image.py +2 -16
  11. dbdicom/{ds/types → sop_classes}/enhanced_mr_image.py +153 -26
  12. dbdicom/{ds/types → sop_classes}/mr_image.py +185 -140
  13. dbdicom/sop_classes/parametric_map.py +307 -0
  14. dbdicom/sop_classes/secondary_capture.py +140 -0
  15. dbdicom/sop_classes/segmentation.py +311 -0
  16. dbdicom/{ds/types → sop_classes}/ultrasound_multiframe_image.py +1 -15
  17. dbdicom/{ds/types → sop_classes}/xray_angiographic_image.py +2 -17
  18. dbdicom/utils/arrays.py +36 -0
  19. dbdicom/utils/files.py +0 -20
  20. dbdicom/utils/image.py +10 -629
  21. dbdicom-0.3.0.dist-info/METADATA +28 -0
  22. dbdicom-0.3.0.dist-info/RECORD +53 -0
  23. dbdicom/create.py +0 -457
  24. dbdicom/dro.py +0 -174
  25. dbdicom/ds/__init__.py +0 -10
  26. dbdicom/ds/create.py +0 -63
  27. dbdicom/ds/dataset.py +0 -869
  28. dbdicom/ds/dictionaries.py +0 -620
  29. dbdicom/ds/types/parametric_map.py +0 -226
  30. dbdicom/extensions/__init__.py +0 -9
  31. dbdicom/extensions/dipy.py +0 -448
  32. dbdicom/extensions/elastix.py +0 -503
  33. dbdicom/extensions/matplotlib.py +0 -107
  34. dbdicom/extensions/numpy.py +0 -271
  35. dbdicom/extensions/scipy.py +0 -1512
  36. dbdicom/extensions/skimage.py +0 -1030
  37. dbdicom/extensions/sklearn.py +0 -243
  38. dbdicom/extensions/vreg.py +0 -1390
  39. dbdicom/manager.py +0 -2132
  40. dbdicom/message.py +0 -119
  41. dbdicom/pipelines.py +0 -66
  42. dbdicom/record.py +0 -1893
  43. dbdicom/types/database.py +0 -107
  44. dbdicom/types/instance.py +0 -231
  45. dbdicom/types/patient.py +0 -40
  46. dbdicom/types/series.py +0 -2874
  47. dbdicom/types/study.py +0 -58
  48. dbdicom-0.2.6.dist-info/METADATA +0 -72
  49. dbdicom-0.2.6.dist-info/RECORD +0 -66
  50. {dbdicom-0.2.6.dist-info → dbdicom-0.3.0.dist-info}/WHEEL +0 -0
  51. {dbdicom-0.2.6.dist-info → dbdicom-0.3.0.dist-info}/licenses/LICENSE +0 -0
  52. {dbdicom-0.2.6.dist-info → dbdicom-0.3.0.dist-info}/top_level.txt +0 -0
@@ -1,271 +0,0 @@
1
- """
2
- ``dbdicom`` extensions calling numpy functions. These do not require additional packages to be installed.
3
- """
4
-
5
- import numpy as np
6
- import dbdicom as dbd
7
-
8
-
9
- def mean_intensity_projection(series:dbd.Series, dims=('SliceLocation','InstanceNumber'), axis=-1) -> dbd.Series:
10
- """Create a mean intensity projection along a specified dimension.
11
-
12
- Args:
13
- series (dbdicom.Series): Original series.
14
- dims (tuple, optional): Dimensions of the array. Defaults to ('SliceLocation','InstanceNumber').
15
- axis (int, optional): axis along which the maximum is to be taken. Defaults to -1.
16
-
17
- Returns:
18
- dbicom.Series: mean intensity projection.
19
-
20
- Example:
21
-
22
- Get the MIP function from the numpy extension to dbdicom:
23
-
24
- >>> from db.extensions.numpy import mean_intensity_projection
25
-
26
- Create a zero-filled array, describing 8 MRI images each measured at 3 flip angles and 2 repetition times:
27
-
28
- >>> coords = {
29
- ... 'SliceLocation': np.arange(8),
30
- ... 'FlipAngle': [2, 15, 30],
31
- ... 'RepetitionTime': [2.5, 5.0],
32
- ... }
33
- >>> series = db.zeros((128,128,8,3,2), coords)
34
-
35
- Create a mean intensity projection on the slice locations and check the dimensions:
36
-
37
- >>> mip = mean_intensity_projection(series)
38
- >>> array = mip.pixel_values(dims=('SliceLocation', 'ImageNumber'))
39
- >>> print(array.shape)
40
- (128, 128, 8, 1)
41
-
42
- Create a mean intensity projection along the Slice Location axis:
43
-
44
- >>> mip = mean_intensity_projection(series, dims=tuple(coords), axis=0)
45
- >>> array = mip.pixel_values(dims=tuple(coords))
46
- >>> print(array.shape)
47
- (128, 128, 1, 3, 2)
48
-
49
- Create a mean intensity projection along the Flip Angle axis:
50
-
51
- >>> mip = mean_intensity_projection(series, dims=tuple(coords), axis=1)
52
- >>> array = mip.pixel_values(dims=tuple(coords))
53
- >>> print(array.shape)
54
- (128, 128, 8, 1, 2)
55
-
56
- Create a mean intensity projection along the Repetition Time axis:
57
-
58
- >>> mip = mean_intensity_projection(series, dims=tuple(coords), axis=2)
59
- >>> array = mip.pixel_values(dims=tuple(coords))
60
- >>> print(array.shape)
61
- (128, 128, 8, 3, 1)
62
- """
63
- array = series.pixel_values(dims=dims)
64
- array = np.mean(array, axis=axis)
65
-
66
- # Save as DICOM
67
- proj = series.new_sibling(SeriesDescription = series.SeriesDescription + '[mean axis ' + str(axis) + ']')
68
- frames = series.frames(dims)
69
- frames = np.take(frames, 0, axis=axis)
70
- frames = frames.ravel()
71
- array = array.reshape((array.shape[0], array.shape[1], -1))
72
- for z in range(frames.size):
73
- series.progress(z+1, frames.size, 'Saving results.. ')
74
- frames_z = frames[z].copy_to(proj)
75
- frames_z.set_pixel_values(array[:,:,z])
76
-
77
- return proj
78
-
79
-
80
- def maximum_intensity_projection(series:dbd.Series, dims=('SliceLocation','InstanceNumber'), axis=-1) -> dbd.Series:
81
- """Create a maximum intensity projection along a specified dimension.
82
-
83
- Args:
84
- series (dbdicom.Series): Original series.
85
- dims (tuple, optional): Dimensions of the array. Defaults to ('SliceLocation','InstanceNumber').
86
- axis (int, optional): axis along which the maximum is to be taken. Defaults to -1.
87
-
88
- Returns:
89
- dbicom.Series: maximum intensity projection.
90
-
91
- Example:
92
-
93
- Get the MIP function from the numpy extension to dbdicom:
94
-
95
- >>> from db.extensions.numpy import maximum_intensity_projection
96
-
97
- Create a zero-filled array, describing 8 MRI images each measured at 3 flip angles and 2 repetition times:
98
-
99
- >>> coords = {
100
- ... 'SliceLocation': np.arange(8),
101
- ... 'FlipAngle': [2, 15, 30],
102
- ... 'RepetitionTime': [2.5, 5.0],
103
- ... }
104
- >>> series = db.zeros((128,128,8,3,2), coords)
105
-
106
- Create a maximum intensity projection on the slice locations and check the dimensions:
107
-
108
- >>> mip = maximum_intensity_projection(series)
109
- >>> array = mip.pixel_values(dims=('SliceLocation', 'ImageNumber'))
110
- >>> print(array.shape)
111
- (128, 128, 8, 1)
112
-
113
- Create a maximum intensity projection along the Slice Location axis:
114
-
115
- >>> mip = maximum_intensity_projection(series, dims=tuple(coords), axis=0)
116
- >>> array = mip.pixel_values(dims=tuple(coords))
117
- >>> print(array.shape)
118
- (128, 128, 1, 3, 2)
119
-
120
- Create a maximum intensity projection along the Flip Angle axis:
121
-
122
- >>> mip = maximum_intensity_projection(series, dims=tuple(coords), axis=1)
123
- >>> array = mip.pixel_values(dims=tuple(coords))
124
- >>> print(array.shape)
125
- (128, 128, 8, 1, 2)
126
-
127
- Create a maximum intensity projection along the Repetition Time axis:
128
-
129
- >>> mip = maximum_intensity_projection(series, dims=tuple(coords), axis=2)
130
- >>> array = mip.pixel_values(dims=tuple(coords))
131
- >>> print(array.shape)
132
- (128, 128, 8, 3, 1)
133
- """
134
-
135
- array = series.pixel_values(dims=dims)
136
- array = np.amax(array, axis=axis)
137
-
138
- # Save as DICOM
139
- proj = series.new_sibling(SeriesDescription = series.SeriesDescription + '[max axis ' + str(axis) + ']')
140
- frames = series.frames(dims)
141
- frames = np.take(frames, 0, axis=axis)
142
- frames = frames.ravel()
143
- array = array.reshape((array.shape[0], array.shape[1], -1))
144
- for z in range(frames.size):
145
- series.progress(z+1, frames.size, 'Saving results.. ')
146
- frames_z = frames[z].copy_to(proj)
147
- frames_z.set_pixel_values(array[:,:,z])
148
-
149
- return proj
150
-
151
-
152
- def norm_projection(series:dbd.Series, dims=('SliceLocation','InstanceNumber'), axis=-1, ord=None) -> dbd.Series:
153
- """Projection along a specified dimension using the vector norm.
154
-
155
- This functions uses numpy.linalg.norm to calculate the projection, see: https://numpy.org/doc/stable/reference/generated/numpy.linalg.norm.html
156
-
157
- Args:
158
- series (dbdicom.Series): Original series.
159
- dims (tuple, optional): Dimensions of the array. Defaults to ('SliceLocation','InstanceNumber').
160
- axis (int, optional): axis along which the maximum is to be taken. Defaults to -1.
161
- ord (int, optional): order of the norm - see documentation of numpy.linalg.norm for details
162
-
163
- Returns:
164
- dbicom.Series: maximum intensity projection.
165
-
166
- Example:
167
-
168
- Get the function from the numpy extension to dbdicom:
169
-
170
- >>> from db.extensions.numpy import norm_projection
171
-
172
- Create a zero-filled array, describing 8 MRI images each measured at 3 flip angles and 2 repetition times:
173
-
174
- >>> coords = {
175
- ... 'SliceLocation': np.arange(8),
176
- ... 'FlipAngle': [2, 15, 30],
177
- ... 'RepetitionTime': [2.5, 5.0],
178
- ... }
179
- >>> series = db.zeros((128,128,8,3,2), coords)
180
-
181
- Create a norm projection on the slice locations and check the dimensions:
182
-
183
- >>> mip = norm_projection(series)
184
- >>> array = mip.pixel_values(dims=('SliceLocation', 'ImageNumber'))
185
- >>> print(array.shape)
186
- (128, 128, 8, 1)
187
-
188
- Create a norm projection along the Slice Location axis:
189
-
190
- >>> mip = norm_projection(series, dims=tuple(coords), axis=0)
191
- >>> array = mip.pixel_values(dims=tuple(coords))
192
- >>> print(array.shape)
193
- (128, 128, 1, 3, 2)
194
-
195
- Create a norm projection along the Flip Angle axis:
196
-
197
- >>> mip = norm_projection(series, dims=tuple(coords), axis=1)
198
- >>> array = mip.pixel_values(dims=tuple(coords))
199
- >>> print(array.shape)
200
- (128, 128, 8, 1, 2)
201
-
202
- Create a norm projection along the Repetition Time axis:
203
-
204
- >>> mip = norm_projection(series, dims=tuple(coords), axis=2)
205
- >>> array = mip.pixel_values(dims=tuple(coords))
206
- >>> print(array.shape)
207
- (128, 128, 8, 3, 1)
208
- """
209
- array = series.pixel_values(dims=dims)
210
- array = np.linalg.norm(array, ord=ord, axis=axis)
211
-
212
- # Save as DICOM
213
- proj = series.new_sibling(SeriesDescription = series.SeriesDescription + '[norm axis ' + str(axis) + ']')
214
- frames = series.frames(dims)
215
- frames = np.take(frames, 0, axis=axis)
216
- frames = frames.ravel()
217
- array = array.reshape((array.shape[0], array.shape[1], -1))
218
- for z in range(frames.size):
219
- series.progress(z+1, frames.size, 'Saving results.. ')
220
- frames_z = frames[z].copy_to(proj)
221
- frames_z.set_pixel_values(array[:,:,z])
222
-
223
- return proj
224
-
225
-
226
-
227
- def threshold(input:dbd.Series, low_threshold=0, high_threshold=1, method='absolute')-> dbd.Series:
228
- """Create a mask series by thresholding.
229
-
230
- Args:
231
- input (dbd.Series): original data to be masked
232
- low_threshold (int, optional): Lower threshold for masking. Defaults to 0.
233
- high_threshold (int, optional): Upper threshold for masking. Defaults to 1.
234
- method (str, optional): Type of thresholding, either 'absolute' (thresholds are absolute signal values), 'quantiles' (thresholds are quantiles), or 'range' (thresholds are between 0 and 1). Defaults to 'absolute'.
235
-
236
- Returns:
237
- dbd.Series: mask series with values = 1 inside and 0 outside.
238
- """
239
- suffix = ' [Threshold segmentation]'
240
- desc = input.instance().SeriesDescription
241
- filtered = input.copy(SeriesDescription = desc+suffix)
242
- #images = filtered.instances()
243
- images = filtered.images()
244
- for i, image in enumerate(images):
245
- input.status.progress(i+1, len(images), 'Filtering ' + desc)
246
- image.read()
247
- array = image.array()
248
- if method == 'quantiles':
249
- range = np.quantile(array, [low_threshold, high_threshold])
250
- elif method == 'range':
251
- min, max = np.amin(array), np.amax(array)
252
- range = [min+low_threshold*(max-min), min+high_threshold*(max-min)]
253
- else:
254
- range = [low_threshold, high_threshold]
255
- array = np.logical_and(array > range[0], array < range[1])
256
- image.set_array(array)
257
- array = array.astype(np.ubyte)
258
- _reset_window(image, array)
259
- image.clear()
260
- input.status.hide()
261
- return filtered
262
-
263
-
264
-
265
- # Helper functions
266
-
267
- def _reset_window(image, array):
268
- min = np.amin(array)
269
- max = np.amax(array)
270
- image.WindowCenter= (max+min)/2
271
- image.WindowWidth = 0.9*(max-min)