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
dbdicom/types/database.py DELETED
@@ -1,107 +0,0 @@
1
- # Importing annotations to handle or sign in import type hints
2
- from __future__ import annotations
3
-
4
- from dbdicom.record import Record
5
- from dbdicom.utils.files import gif2numpy
6
-
7
- class Database(Record):
8
-
9
- name = 'Database'
10
-
11
- def loc(self):
12
- return self.manager._dbloc()
13
- # df = self.manager.register
14
- # return df.removed==False
15
-
16
- def _set_key(self):
17
- #if not self.manager.register.empty:
18
- if not self.manager._empty():
19
- self._key = self.manager._keys(0)
20
- #self._key = self.manager.register.index[0]
21
- else:
22
- self._key = None
23
-
24
- def close(self):
25
- return self.manager.close()
26
-
27
- def set_path(self,path):
28
- # Used in example of clear
29
- self.manager.path=path
30
-
31
- def parent(self):
32
- return
33
-
34
- def children(self, **kwargs):
35
- return self.patients(**kwargs)
36
-
37
- def new_child(self, dataset=None, **kwargs):
38
- attr = {**kwargs, **self.attributes}
39
- return self.new_patient(**attr)
40
-
41
- def new_sibling(self, suffix=None, **kwargs):
42
- msg = 'You cannot create a sibling from a database \n'
43
- msg += 'You can start a new database with db.database()'
44
- raise RuntimeError(msg)
45
-
46
- def save(self, path=None):
47
- #self.manager.save('Database')
48
- self.manager.save()
49
- self.write(path)
50
-
51
- def restore(self, path=None):
52
- self.manager.restore()
53
- self.write(path)
54
-
55
- def open(self, path):
56
- self.manager.open(path)
57
-
58
- def close(self):
59
- return self.manager.close()
60
-
61
- def scan(self):
62
- self.manager.scan()
63
-
64
- def import_dicom(self, files):
65
- uids = self.manager.import_datasets(files)
66
- return uids is not None
67
-
68
- def import_nifti(self, files):
69
- self.manager.import_datasets_from_nifti(files)
70
-
71
- def import_gif(self, files):
72
- study = self.new_patient().new_study()
73
- for file in files:
74
- array = gif2numpy(file)
75
- series = study.new_series()
76
- series.set_array(array)
77
- return study
78
-
79
- def _copy_from(self, record):
80
- uids = self.manager.copy_to_database(record.uid, **self.attributes)
81
- if isinstance(uids, list):
82
- return [self.record('Patient', uid, **self.attributes) for uid in uids]
83
- else:
84
- return self.record('Patient', uids, **self.attributes)
85
-
86
- def zeros(*args, **kwargs): # OBSOLETE - remove
87
- return zeros(*args, **kwargs)
88
-
89
- # def export_as_dicom(self, path):
90
- # for child in self.children():
91
- # child.export_as_dicom(path)
92
-
93
- # def export_as_png(self, path):
94
- # for child in self.children():
95
- # child.export_as_png(path)
96
-
97
- # def export_as_csv(self, path):
98
- # for child in self.children():
99
- # child.export_as_csv(path)
100
-
101
-
102
- def zeros(database, shape, dtype='mri'): # OBSOLETE - remove
103
- study = database.new_study()
104
- return study.zeros(shape, dtype=dtype)
105
-
106
-
107
-
dbdicom/types/instance.py DELETED
@@ -1,231 +0,0 @@
1
- # Importing annotations to handle or sign in import type hints
2
- from __future__ import annotations
3
-
4
- import timeit
5
- import os
6
- import numpy as np
7
- import nibabel as nib
8
- import pandas as pd
9
- import matplotlib.pyplot as plt
10
- import vreg
11
-
12
-
13
- from dbdicom.record import Record
14
- from dbdicom.ds.create import new_dataset
15
- import dbdicom.utils.image as image
16
-
17
-
18
- class Instance(Record):
19
-
20
- name = 'SOPInstanceUID'
21
-
22
- def keys(self):
23
- return [self.key()]
24
-
25
- def parent(self):
26
- #uid = self.manager.register.at[self.key(), 'SeriesInstanceUID']
27
- uid = self.manager._at(self.key(), 'SeriesInstanceUID')
28
- return self.record('Series', uid, key=self.key())
29
-
30
- def children(self, **kwargs):
31
- return
32
-
33
- def new_child(self, **kwargs):
34
- return
35
-
36
- def _copy_from(self, record, **kwargs):
37
- return
38
-
39
- def copy_to_series(self, series):
40
- uid = self.manager.copy_instance_to_series(self.key(), series.keys(), series)
41
- return self.record('Instance', uid)
42
-
43
- def pixel_values(self):
44
- return self.get_pixel_array()
45
-
46
- def set_pixel_values(self, array):
47
- self.set_pixel_array(array)
48
-
49
- def set_dataset(self, dataset):
50
- self._key = self.manager.set_instance_dataset(self.uid, dataset, self.key())
51
-
52
- def map_to(self, target):
53
- return map_to(self, target)
54
-
55
- def map_mask_to(self, target):
56
- return map_mask_to(self, target)
57
-
58
-
59
- def export_as_png(self, path, center=None, width=None, colormap=None):
60
- # Export image in png format.
61
- if center is None or width is None:
62
- c, w = self.window
63
- if center is None:
64
- center = c
65
- if width is None:
66
- width = w
67
- if colormap is None:
68
- colormap = self.colormap
69
- if colormap is None:
70
- colormap = 'gray'
71
-
72
- vmin = center - width/2
73
- vmax = center + width/2
74
- array = np.transpose(self.array())
75
- plt.imshow(array, cmap=colormap, vmin=vmin, vmax=vmax)
76
- cBar = plt.colorbar()
77
- cBar.minorticks_on()
78
- filename = self.label()
79
- filename = os.path.join(path, filename + '.png')
80
- plt.savefig(fname=filename)
81
- plt.close()
82
-
83
-
84
- def export_as_csv(self, path):
85
- # Export 2D pixel Array in csv format
86
- table = np.transpose(self.array())
87
- cols = ['Column' + str(x) for x in range(table.shape[0])]
88
- rows = ['Row' + str(y) for y in range(table.shape[1])]
89
- filepath = self.label()
90
- filepath = os.path.join(path, filepath + '.csv')
91
- df = pd.DataFrame(table, index=rows, columns=cols)
92
- df.to_csv(filepath)
93
-
94
-
95
- def export_as_nifti(self, path, affine=None):
96
- # Export series as a single Nifty file
97
- ds = self.get_dataset()
98
- if affine is None:
99
- affine = ds.get_values('affine_matrix')
100
- array = self.array()
101
- dicomHeader = nib.nifti1.Nifti1DicomExtension(2, ds)
102
- niftiObj = nib.Nifti1Image(array, image.affine_to_RAH(affine))
103
- niftiObj.header.extensions.append(dicomHeader)
104
- filepath = self.label()
105
- filepath = os.path.join(path, filepath + '.nii')
106
- nib.save(niftiObj, filepath)
107
-
108
-
109
- def export_as_npy(self, path):
110
- # Export instance as a single NPY file
111
- array = self.array()
112
- filepath = self.label()
113
- filepath = os.path.join(path, filepath + '.npy')
114
- with open(filepath, 'wb') as f:
115
- np.save(f, array)
116
-
117
-
118
- def BGRA_array(self):
119
- return image.BGRA(
120
- self.get_pixel_array(),
121
- self.lut,
122
- width = self.WindowWidth,
123
- center = self.WindowCenter,
124
- )
125
-
126
- def volume(self):
127
- return vreg.volume(self.pixel_values(),
128
- self.affine())
129
-
130
- def set_volume(self, volume:vreg.Volume3D):
131
- self.set_pixel_values(np.squeeze(volume.values))
132
- self.set_affine(volume.affine)
133
-
134
- def affine(self):
135
- return image.affine_matrix(self.ImageOrientationPatient,
136
- self.ImagePositionPatient,
137
- self.PixelSpacing,
138
- self.SliceThickness)
139
-
140
- def set_affine(self, affine):
141
- p = image.dismantle_affine_matrix(affine)
142
- self.read()
143
- #self.SpacingBetweenSlices = p['SpacingBetweenSlices']
144
- self.SliceThickness = p['SliceThickness']
145
- self.PixelSpacing = p['PixelSpacing']
146
- self.ImageOrientationPatient = p['ImageOrientationPatient']
147
- self.ImagePositionPatient = p['ImagePositionPatient']
148
- self.SliceLocation = np.dot(p['ImagePositionPatient'], p['slice_cosine'])
149
- self.clear()
150
-
151
-
152
- # OBSOLETE API
153
-
154
- def array(self): # obsolete replace by pixel_values
155
- return self.get_pixel_array()
156
-
157
- def get_pixel_array(self): # obsolete replace by pixel_values
158
- ds = self.get_dataset()
159
- return ds.get_pixel_array()
160
-
161
- def set_array(self, array): # obsolete replace by set_pixel_values
162
- self.set_pixel_array(array)
163
-
164
- def set_pixel_array(self, array): # obsolete replace by set_pixel_values
165
- ds = self.get_dataset()
166
- if ds is None:
167
- ds = new_dataset('MRImage')
168
- ds.set_pixel_array(array)
169
- in_memory = self.key() in self.manager.dataset
170
- self.set_dataset(ds)
171
- # This bit added ad-hoc because set_dataset() places the datset in memory
172
- # So if the instance is not in memory, it needs to be written and removed again
173
- if not in_memory:
174
- self.clear()
175
-
176
-
177
- def map_to(source, target):
178
- """Map non-zero image pixels onto a target image.
179
-
180
- Overwrite pixel values in the target"""
181
-
182
- dss = source.get_dataset()
183
- dst = target.get_dataset()
184
-
185
- # Create a coordinate array for all pixels in the source
186
- coords = np.empty((dss.Rows*dss.Columns, 3), dtype=np.uint16)
187
- for x in range(dss.Columns):
188
- for y in range(dss.Rows):
189
- coords[x*dss.Columns+y,:] = [x,y,0]
190
-
191
- # Apply coordinate transformation from source to target
192
- affineSource = dss.get_affine_matrix()
193
- affineTarget = dst.get_affine_matrix()
194
- sourceToTarget = np.linalg.inv(affineTarget).dot(affineSource)
195
- coords_target = nib.affines.apply_affine(sourceToTarget, coords)
196
-
197
- # Interpolate (nearest neighbour) and extract inslice coordinates
198
- coords_target = np.round(coords_target, 3).astype(int)
199
- xt = tuple([c[0] for c in coords_target if c[2] == 0])
200
- yt = tuple([c[1] for c in coords_target if c[2] == 0])
201
- xs = tuple([c[0] for c in coords])
202
- ys = tuple([c[1] for c in coords])
203
-
204
- ## COORDINATES DO NOT MATCH UP because of c[2] = 0 condition
205
- ## Needs a different indexing approach
206
-
207
- # Set values in the target image
208
- source_array = dss.get_pixel_array()
209
- target_array = np.zeros((dst.Columns, dst.Rows))
210
- target_array[(xt, yt)] = source_array[(xs, ys)]
211
- # for masking map values to {0, 1}
212
- result = source.new_sibling()
213
- result.set_pixel_array(target_array)
214
-
215
- return result
216
-
217
- # Obsolete
218
- def map_mask_to(record, target):
219
- """Map non-zero image pixels onto a target image.
220
- Overwrite pixel values in the target"""
221
- dsr = record.get_dataset()
222
- dst = target.get_dataset()
223
- array = dsr.map_mask_to(dst)
224
- result = target.copy_to(record.parent()) # inherit geometry header from target
225
- result.set_pixel_array(array)
226
- return result
227
-
228
-
229
-
230
-
231
-
dbdicom/types/patient.py DELETED
@@ -1,40 +0,0 @@
1
- # Importing annotations to handle or sign in import type hints
2
- from __future__ import annotations
3
-
4
- from dbdicom.record import Record
5
-
6
- class Patient(Record):
7
-
8
- name = 'PatientID'
9
-
10
- def new_study(self, **kwargs):
11
- attr = {**kwargs, **self.attributes}
12
- uid, key = self.manager.new_study(parent=self.uid, key=self.key(), **attr)
13
- return self.record('Study', uid, key, **attr)
14
-
15
- def parent(self):
16
- return self.record('Database')
17
-
18
- def children(self, **kwargs):
19
- return self.studies(**kwargs)
20
-
21
- def new_child(self, dataset=None, **kwargs):
22
- attr = {**kwargs, **self.attributes}
23
- return self.new_study(**attr)
24
-
25
- def new_sibling(self, suffix=None, **kwargs):
26
- if suffix is not None:
27
- desc = self.manager._at(self.key(), 'PatientName')
28
- kwargs['PatientName'] = desc + ' [' + suffix + ']'
29
- return self.parent().new_child(**kwargs)
30
-
31
- def _copy_from(self, record, **kwargs):
32
- attr = {**kwargs, **self.attributes}
33
- uids = self.manager.copy_to_patient(record.uid, self.key(), **attr)
34
- if isinstance(uids, list):
35
- return [self.record('Study', uid, **attr) for uid in uids]
36
- else:
37
- return self.record('Study', uids, **attr)
38
-
39
-
40
-