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.
- dbdicom/__init__.py +1 -28
- dbdicom/api.py +287 -0
- dbdicom/const.py +144 -0
- dbdicom/dataset.py +721 -0
- dbdicom/dbd.py +736 -0
- dbdicom/external/__pycache__/__init__.cpython-311.pyc +0 -0
- dbdicom/external/dcm4che/__pycache__/__init__.cpython-311.pyc +0 -0
- dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-311.pyc +0 -0
- dbdicom/register.py +527 -0
- dbdicom/{ds/types → sop_classes}/ct_image.py +2 -16
- dbdicom/{ds/types → sop_classes}/enhanced_mr_image.py +153 -26
- dbdicom/{ds/types → sop_classes}/mr_image.py +185 -140
- dbdicom/sop_classes/parametric_map.py +310 -0
- dbdicom/sop_classes/secondary_capture.py +140 -0
- dbdicom/sop_classes/segmentation.py +311 -0
- dbdicom/{ds/types → sop_classes}/ultrasound_multiframe_image.py +1 -15
- dbdicom/{ds/types → sop_classes}/xray_angiographic_image.py +2 -17
- dbdicom/utils/arrays.py +36 -0
- dbdicom/utils/files.py +0 -20
- dbdicom/utils/image.py +10 -629
- dbdicom-0.3.1.dist-info/METADATA +28 -0
- dbdicom-0.3.1.dist-info/RECORD +53 -0
- dbdicom/create.py +0 -457
- dbdicom/dro.py +0 -174
- dbdicom/ds/__init__.py +0 -10
- dbdicom/ds/create.py +0 -63
- dbdicom/ds/dataset.py +0 -869
- dbdicom/ds/dictionaries.py +0 -620
- dbdicom/ds/types/parametric_map.py +0 -226
- dbdicom/extensions/__init__.py +0 -9
- dbdicom/extensions/dipy.py +0 -448
- dbdicom/extensions/elastix.py +0 -503
- dbdicom/extensions/matplotlib.py +0 -107
- dbdicom/extensions/numpy.py +0 -271
- dbdicom/extensions/scipy.py +0 -1512
- dbdicom/extensions/skimage.py +0 -1030
- dbdicom/extensions/sklearn.py +0 -243
- dbdicom/extensions/vreg.py +0 -1390
- dbdicom/manager.py +0 -2132
- dbdicom/message.py +0 -119
- dbdicom/pipelines.py +0 -66
- dbdicom/record.py +0 -1893
- dbdicom/types/database.py +0 -107
- dbdicom/types/instance.py +0 -231
- dbdicom/types/patient.py +0 -40
- dbdicom/types/series.py +0 -2874
- dbdicom/types/study.py +0 -58
- dbdicom-0.2.6.dist-info/METADATA +0 -72
- dbdicom-0.2.6.dist-info/RECORD +0 -66
- {dbdicom-0.2.6.dist-info → dbdicom-0.3.1.dist-info}/WHEEL +0 -0
- {dbdicom-0.2.6.dist-info → dbdicom-0.3.1.dist-info}/licenses/LICENSE +0 -0
- {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
|
-
|