dbdicom 0.2.6__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.

Files changed (52) hide show
  1. dbdicom/__init__.py +1 -28
  2. dbdicom/api.py +287 -0
  3. dbdicom/const.py +144 -0
  4. dbdicom/dataset.py +721 -0
  5. dbdicom/dbd.py +736 -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 +310 -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.1.dist-info/METADATA +28 -0
  22. dbdicom-0.3.1.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.1.dist-info}/WHEEL +0 -0
  51. {dbdicom-0.2.6.dist-info → dbdicom-0.3.1.dist-info}/licenses/LICENSE +0 -0
  52. {dbdicom-0.2.6.dist-info → dbdicom-0.3.1.dist-info}/top_level.txt +0 -0
@@ -1,243 +0,0 @@
1
- import numpy as np
2
- from sklearn.cluster import KMeans
3
- from sklearn.preprocessing import StandardScaler
4
- from dbdicom.extensions import scipy, vreg
5
-
6
-
7
- # https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans
8
- def kmeans(features, mask=None, n_clusters=2, multiple_series=False, normalize=True, return_features=False):
9
- """
10
- Labels structures in an image
11
-
12
- Wrapper for sklearn.cluster.KMeans function.
13
-
14
- Parameters
15
- ----------
16
- input: list of dbdicom series (one for each feature)
17
- mask: optional mask for clustering
18
-
19
- Returns
20
- -------
21
- clusters : list of dbdicom series, with labels per cluster.
22
- """
23
-
24
- # If a mask is provided, map it onto the reference feature and
25
- # extract the indices of all pixels under the mask
26
- if mask is not None:
27
- mask.message('Reading mask array..')
28
- #mask = vreg.map_to(mask, features[0], mask=True)
29
- #mask_array, _ = mask.array(['SliceLocation', 'AcquisitionTime'], pixels_first=True)
30
- mask_array, _ = vreg.mask_array(mask, on=features[0], dim='AcquisitionTime')
31
- mask_array = np.ravel(mask_array)
32
- mask_indices = tuple(mask_array.nonzero())
33
-
34
- # Ensure all the features are in the same geometry as the reference feature
35
- features = scipy.overlay(features)
36
-
37
- # Create array with shape (n_samples, n_features) and mask if needed.
38
- array = []
39
- for s, series in enumerate(features):
40
- series.progress(s+1, len(features), 'Reading features..')
41
- arr, headers = series.array(['SliceLocation', 'AcquisitionTime'], pixels_first=True)
42
- shape = arr.shape
43
- arr = np.ravel(arr)
44
- if mask is not None:
45
- arr = arr[mask_indices]
46
- #if normalize:
47
- # arr = (arr-np.mean(arr))/np.std(arr)
48
- array.append(arr)
49
- array = np.vstack(array).T
50
-
51
- # Perform the K-Means clustering.
52
- series.message('Clustering. Please be patient - this is hard work..')
53
- if normalize:
54
- X = StandardScaler().fit_transform(array)
55
- kmeans = KMeans(n_clusters=n_clusters, random_state=0, n_init=3, verbose=1).fit(X)
56
- else:
57
- kmeans = KMeans(n_clusters=n_clusters, random_state=0, n_init=3, verbose=1).fit(array)
58
-
59
- # Create an output array for the labels
60
- if mask is not None:
61
- mask.message('Creating output array..')
62
- output_array = np.zeros(shape)
63
- output_array = np.ravel(output_array)
64
- output_array[mask_indices] = 1+kmeans.labels_
65
- else:
66
- output_array = 1+kmeans.labels_
67
- output_array = output_array.reshape(shape)
68
-
69
- # Save the results in DICOM
70
- series.message('Saving clusters..')
71
- if multiple_series:
72
- # Save each cluster as a separate mask
73
- clusters = []
74
- for cluster in range(1,1+n_clusters):
75
- array_cluster = np.zeros(output_array.shape)
76
- array_cluster[output_array == cluster] = 1
77
- series_cluster = features[0].new_sibling(SeriesDescription = 'KMeans cluster ' + str(cluster))
78
- series_cluster.set_array(array_cluster, headers, pixels_first=True)
79
- _reset_window(series_cluster, array_cluster)
80
- clusters.append(series_cluster)
81
- else:
82
- # Save the label array in a single series
83
- clusters = features[0].new_sibling(SeriesDescription = 'KMeans')
84
- clusters.set_array(output_array, headers, pixels_first=True)
85
- _reset_window(clusters, output_array)
86
-
87
- # If requested, return features (mean values over clusters + size of cluster)
88
- if return_features: # move up
89
- cluster_features = []
90
- for cluster in range(1,1+n_clusters):
91
- vals = []
92
- #locs = (output_array.ravel() == cluster)
93
- locs = (1+kmeans.labels_ == cluster)
94
- for feature in range(array.shape[1]):
95
- val = np.mean(array[:,feature][locs])
96
- vals.append(val)
97
- vals.append(np.sum(locs))
98
- cluster_features.append(vals)
99
- return clusters, cluster_features
100
-
101
- return clusters
102
-
103
-
104
- def kmeans_4d(features, mask=None, n_clusters=2, multiple_series=False, normalize=True, return_features=False):
105
-
106
- # If a mask is provided, map it onto the reference feature and
107
- # extract the indices of all pixels under the mask
108
- if mask is not None:
109
- mask.message('Reading mask array..')
110
- mask_array, _ = vreg.mask_array(mask, on=features[0], dim='AcquisitionTime')
111
- mask_array = np.ravel(mask_array)
112
- mask_indices = tuple(mask_array.nonzero())
113
-
114
- # Create array with shape (n_samples, n_features) and mask if needed.
115
- array, headers = features.array(['SliceLocation', 'AcquisitionTime'], pixels_first=True)
116
- shape = array.shape
117
- array = array.reshape((-1, shape[-1]))
118
- if mask is not None:
119
- array = array[mask_indices, :]
120
-
121
- # Perform the K-Means clustering.
122
- features.message('Clustering. Please be patient - this is hard work..')
123
- if normalize:
124
- X = StandardScaler().fit_transform(array)
125
- kmeans = KMeans(n_clusters=n_clusters, random_state=0, n_init=3, verbose=1).fit(X)
126
- else:
127
- kmeans = KMeans(n_clusters=n_clusters, random_state=0, n_init=3, verbose=1).fit(array)
128
-
129
- # Create an output array for the labels
130
- if mask is not None:
131
- mask.message('Creating output array..')
132
- output_array = np.zeros(shape)
133
- output_array = np.ravel(output_array)
134
- output_array[mask_indices] = 1+kmeans.labels_
135
- else:
136
- output_array = 1+kmeans.labels_
137
- output_array = output_array.reshape(shape)
138
-
139
- # Save the results in DICOM
140
- features.message('Saving clusters..')
141
- if multiple_series:
142
- # Save each cluster as a separate mask
143
- clusters = []
144
- for cluster in range(1,1+n_clusters):
145
- array_cluster = np.zeros(output_array.shape)
146
- array_cluster[output_array == cluster] = 1
147
- series_cluster = features[0].new_sibling(SeriesDescription = 'KMeans cluster ' + str(cluster))
148
- series_cluster.set_array(array_cluster, headers, pixels_first=True)
149
- _reset_window(series_cluster, array_cluster)
150
- clusters.append(series_cluster)
151
- else:
152
- # Save the label array in a single series
153
- clusters = features[0].new_sibling(SeriesDescription = 'KMeans')
154
- clusters.set_array(output_array, headers, pixels_first=True)
155
- _reset_window(clusters, output_array)
156
-
157
- # If requested, return features (mean values over clusters + size of cluster)
158
- if return_features: # move up
159
- cluster_features = []
160
- for cluster in range(1,1+n_clusters):
161
- vals = []
162
- #locs = (output_array.ravel() == cluster)
163
- locs = (1+kmeans.labels_ == cluster)
164
- for feature in range(array.shape[1]):
165
- val = np.mean(array[:,feature][locs])
166
- vals.append(val)
167
- vals.append(np.sum(locs))
168
- cluster_features.append(vals)
169
- return clusters, cluster_features
170
-
171
- return clusters
172
-
173
-
174
-
175
- def sequential_kmeans(features, mask=None, n_clusters=2, multiple_series=False):
176
- """
177
- Labels structures in an image using sequential k-means clustering
178
-
179
- Sequential here means that the clustering is always performed on a single feature
180
- using the output of the previous iteration as a mask for the next.
181
-
182
- Parameters
183
- ----------
184
- input: list of dbdicom series (one for each feature)
185
- mask: optional mask for clustering
186
-
187
- Returns
188
- -------
189
- clusters : list of dbdicom series, with labels per cluster.
190
- """
191
-
192
- f = features[0]
193
- clusters = kmeans([f], mask=mask, n_clusters=n_clusters, multiple_series=True)
194
- for f in features[1:]:
195
- cf = []
196
- for mask in clusters:
197
- cf += kmeans([f], mask=mask, n_clusters=n_clusters, multiple_series=True)
198
- mask.remove()
199
- clusters = cf
200
-
201
- # Return clusters as a list
202
- if multiple_series:
203
- return clusters
204
-
205
- # Return a single label series
206
- label = masks_to_label(clusters)
207
- for c in clusters:
208
- c.remove()
209
- return label
210
-
211
-
212
-
213
- def masks_to_label(masks):
214
- "Convert a list of masks into a single label series"
215
-
216
- # Ensure all the masks are in the same geometry
217
- masks = scipy.overlay(masks)
218
-
219
- # Create a single label array
220
- array, headers = masks[0].array(['SliceLocation', 'AcquisitionTime'], pixels_first=True)
221
- msg = 'Creating a single label image'
222
- for m, mask in enumerate(masks[1:]):
223
- mask.status.progress(m+1, len(masks)-1, msg)
224
- arr, _ = mask.array(['SliceLocation', 'AcquisitionTime'], pixels_first=True)
225
- ind = tuple(arr.nonzero())
226
- array[ind] = m+2
227
-
228
- # Save label array to disk
229
- desc = masks[0].SeriesDescription
230
- label = masks[0].new_sibling(SeriesDescription = desc + ' [Label]')
231
- label.set_array(array, headers, pixels_first=True)
232
-
233
- return label
234
-
235
-
236
-
237
- # Helper functions
238
-
239
- def _reset_window(image, array):
240
- min = np.amin(array)
241
- max = np.amax(array)
242
- image.WindowCenter= (max+min)/2
243
- image.WindowWidth = 0.9*(max-min)