dbdicom 0.2.0__py3-none-any.whl → 0.3.16__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.
- dbdicom/__init__.py +3 -25
- dbdicom/api.py +496 -0
- dbdicom/const.py +144 -0
- dbdicom/database.py +133 -0
- dbdicom/dataset.py +471 -0
- dbdicom/dbd.py +1290 -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/external/dcm4che/bin/emf2sf +57 -57
- dbdicom/register.py +402 -0
- dbdicom/{ds/types → sop_classes}/ct_image.py +2 -16
- dbdicom/{ds/types → sop_classes}/enhanced_mr_image.py +206 -160
- dbdicom/sop_classes/mr_image.py +338 -0
- dbdicom/sop_classes/parametric_map.py +381 -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 +142 -0
- dbdicom/utils/files.py +0 -20
- dbdicom/utils/image.py +43 -466
- dbdicom/utils/pydicom_dataset.py +386 -0
- dbdicom-0.3.16.dist-info/METADATA +26 -0
- dbdicom-0.3.16.dist-info/RECORD +54 -0
- {dbdicom-0.2.0.dist-info → dbdicom-0.3.16.dist-info}/WHEEL +1 -1
- dbdicom/create.py +0 -450
- dbdicom/ds/__init__.py +0 -10
- dbdicom/ds/create.py +0 -63
- dbdicom/ds/dataset.py +0 -841
- dbdicom/ds/dictionaries.py +0 -620
- dbdicom/ds/types/mr_image.py +0 -267
- dbdicom/ds/types/parametric_map.py +0 -226
- dbdicom/external/__pycache__/__init__.cpython-310.pyc +0 -0
- dbdicom/external/__pycache__/__init__.cpython-37.pyc +0 -0
- dbdicom/external/dcm4che/__pycache__/__init__.cpython-310.pyc +0 -0
- dbdicom/external/dcm4che/__pycache__/__init__.cpython-37.pyc +0 -0
- dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-310.pyc +0 -0
- dbdicom/external/dcm4che/bin/__pycache__/__init__.cpython-37.pyc +0 -0
- dbdicom/external/dcm4che/lib/linux-x86/libclib_jiio.so +0 -0
- dbdicom/external/dcm4che/lib/linux-x86-64/libclib_jiio.so +0 -0
- dbdicom/external/dcm4che/lib/linux-x86-64/libopencv_java.so +0 -0
- dbdicom/external/dcm4che/lib/solaris-sparc/libclib_jiio.so +0 -0
- dbdicom/external/dcm4che/lib/solaris-sparc/libclib_jiio_vis.so +0 -0
- dbdicom/external/dcm4che/lib/solaris-sparc/libclib_jiio_vis2.so +0 -0
- dbdicom/external/dcm4che/lib/solaris-sparcv9/libclib_jiio.so +0 -0
- dbdicom/external/dcm4che/lib/solaris-sparcv9/libclib_jiio_vis.so +0 -0
- dbdicom/external/dcm4che/lib/solaris-sparcv9/libclib_jiio_vis2.so +0 -0
- dbdicom/external/dcm4che/lib/solaris-x86/libclib_jiio.so +0 -0
- dbdicom/external/dcm4che/lib/solaris-x86-64/libclib_jiio.so +0 -0
- dbdicom/manager.py +0 -2077
- dbdicom/message.py +0 -119
- dbdicom/record.py +0 -1526
- dbdicom/types/database.py +0 -107
- dbdicom/types/instance.py +0 -184
- dbdicom/types/patient.py +0 -40
- dbdicom/types/series.py +0 -816
- dbdicom/types/study.py +0 -58
- dbdicom/utils/variables.py +0 -155
- dbdicom/utils/vreg.py +0 -2626
- dbdicom/wrappers/__init__.py +0 -7
- dbdicom/wrappers/dipy.py +0 -462
- dbdicom/wrappers/elastix.py +0 -855
- dbdicom/wrappers/numpy.py +0 -119
- dbdicom/wrappers/scipy.py +0 -1413
- dbdicom/wrappers/skimage.py +0 -1030
- dbdicom/wrappers/sklearn.py +0 -151
- dbdicom/wrappers/vreg.py +0 -273
- dbdicom-0.2.0.dist-info/METADATA +0 -276
- dbdicom-0.2.0.dist-info/RECORD +0 -81
- {dbdicom-0.2.0.dist-info → dbdicom-0.3.16.dist-info/licenses}/LICENSE +0 -0
- {dbdicom-0.2.0.dist-info → dbdicom-0.3.16.dist-info}/top_level.txt +0 -0
dbdicom/ds/types/mr_image.py
DELETED
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
# Coded version of DICOM file
|
|
2
|
-
# 'RIDER Neuro MRI-3369019796\03-21-1904-BRAINRESEARCH-00598\14.000000-sag 3d gre c-04769\1-010.dcm'
|
|
3
|
-
# Produced by pydicom codify utility script
|
|
4
|
-
import struct
|
|
5
|
-
import numpy as np
|
|
6
|
-
import pydicom
|
|
7
|
-
from pydicom.dataset import Dataset, FileMetaDataset
|
|
8
|
-
from pydicom.sequence import Sequence
|
|
9
|
-
|
|
10
|
-
from dbdicom.ds.dataset import DbDataset
|
|
11
|
-
import dbdicom.utils.image as image
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class MRImage(DbDataset):
|
|
15
|
-
|
|
16
|
-
def __init__(self, dataset=None, template=None):
|
|
17
|
-
super().__init__()
|
|
18
|
-
|
|
19
|
-
if (dataset is None) and (template is None):
|
|
20
|
-
template = 'RIDER'
|
|
21
|
-
|
|
22
|
-
if dataset is not None:
|
|
23
|
-
self.__dict__ = dataset.__dict__
|
|
24
|
-
|
|
25
|
-
if template == 'RIDER':
|
|
26
|
-
rider(self)
|
|
27
|
-
|
|
28
|
-
def get_pixel_array(self):
|
|
29
|
-
return get_pixel_array(self)
|
|
30
|
-
|
|
31
|
-
def set_pixel_array(self, array):
|
|
32
|
-
set_pixel_array(self, array)
|
|
33
|
-
|
|
34
|
-
def get_attribute_image_type(self):
|
|
35
|
-
return get_attribute_image_type(self)
|
|
36
|
-
|
|
37
|
-
def set_attribute_image_type(self, value):
|
|
38
|
-
set_attribute_image_type(self, value)
|
|
39
|
-
|
|
40
|
-
def get_attribute_signal_type(self):
|
|
41
|
-
return get_attribute_signal_type(self)
|
|
42
|
-
|
|
43
|
-
def set_attribute_signal_type(self, value):
|
|
44
|
-
set_attribute_signal_type(self, value)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def rider(ds): # required only - check
|
|
49
|
-
|
|
50
|
-
# File meta info data elements
|
|
51
|
-
ds.file_meta = FileMetaDataset()
|
|
52
|
-
ds.file_meta.FileMetaInformationGroupLength = 190
|
|
53
|
-
ds.file_meta.FileMetaInformationVersion = b'\x00\x01'
|
|
54
|
-
ds.file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.4'
|
|
55
|
-
ds.file_meta.MediaStorageSOPInstanceUID = '1.3.6.1.4.1.9328.50.16.175333593952805976694548436931998383940'
|
|
56
|
-
ds.file_meta.TransferSyntaxUID = '1.2.840.10008.1.2'
|
|
57
|
-
ds.file_meta.ImplementationClassUID = '1.2.40.0.13.1.1'
|
|
58
|
-
ds.file_meta.ImplementationVersionName = 'dcm4che-1.4.27'
|
|
59
|
-
|
|
60
|
-
ds.is_implicit_VR = True
|
|
61
|
-
ds.is_little_endian = True
|
|
62
|
-
|
|
63
|
-
# Main data elements
|
|
64
|
-
ds.SpecificCharacterSet = 'ISO_IR 100'
|
|
65
|
-
ds.ImageType = ['ORIGINAL', 'PRIMARY', 'M', 'ND', 'NORM']
|
|
66
|
-
ds.SOPClassUID = '1.2.840.10008.5.1.4.1.1.4'
|
|
67
|
-
ds.SOPInstanceUID = pydicom.uid.generate_uid()
|
|
68
|
-
ds.StudyDate = '19040321'
|
|
69
|
-
ds.ContentDate = '19040321'
|
|
70
|
-
ds.StudyTime = ''
|
|
71
|
-
ds.AcquisitionTime = '075649.057496'
|
|
72
|
-
ds.ContentTime = ''
|
|
73
|
-
ds.AccessionNumber = '2819497684894126'
|
|
74
|
-
ds.Modality = 'MR'
|
|
75
|
-
ds.Manufacturer = 'SIEMENS'
|
|
76
|
-
ds.ReferringPhysicianName = ''
|
|
77
|
-
ds.StationName = ''
|
|
78
|
-
ds.StudyDescription = 'BRAIN^RESEARCH'
|
|
79
|
-
ds.SeriesDescription = 'sag 3d gre +c'
|
|
80
|
-
ds.ManufacturerModelName = ''
|
|
81
|
-
ds.ReferencedSOPClassUID = '1.3.6.1.4.1.9328.50.16.295504506656781074046411123909869020125'
|
|
82
|
-
ds.ReferencedSOPInstanceUID = '1.3.6.1.4.1.9328.50.16.303143938897288157958328401346374476407'
|
|
83
|
-
ds.PatientName = '281949'
|
|
84
|
-
ds.PatientID = pydicom.uid.generate_uid()
|
|
85
|
-
ds.PatientBirthDate = ''
|
|
86
|
-
ds.PatientSex = ''
|
|
87
|
-
ds.PatientIdentityRemoved = 'YES'
|
|
88
|
-
ds.DeidentificationMethod = 'CTP:NBIA Default w/ extra date removal:20100323:172722'
|
|
89
|
-
ds.ContrastBolusAgent = 'Magnevist'
|
|
90
|
-
ds.BodyPartExamined = 'FAKE'
|
|
91
|
-
ds.ScanningSequence = 'GR'
|
|
92
|
-
ds.SequenceVariant = 'SP'
|
|
93
|
-
ds.ScanOptions = ''
|
|
94
|
-
ds.MRAcquisitionType = '3D'
|
|
95
|
-
ds.SequenceName = '*fl3d1'
|
|
96
|
-
ds.AngioFlag = 'N'
|
|
97
|
-
ds.SliceThickness = '1.0'
|
|
98
|
-
ds.RepetitionTime = '8.6'
|
|
99
|
-
ds.EchoTime = '4.11'
|
|
100
|
-
ds.NumberOfAverages = '1.0'
|
|
101
|
-
ds.ImagingFrequency = '63.676701'
|
|
102
|
-
ds.ImagedNucleus = '1H'
|
|
103
|
-
ds.EchoNumbers = '0'
|
|
104
|
-
ds.MagneticFieldStrength = '1.4939999580383'
|
|
105
|
-
ds.NumberOfPhaseEncodingSteps = '224'
|
|
106
|
-
ds.EchoTrainLength = '1'
|
|
107
|
-
ds.PercentSampling = '100.0'
|
|
108
|
-
ds.PercentPhaseFieldOfView = '100.0'
|
|
109
|
-
ds.PixelBandwidth = '150.0'
|
|
110
|
-
ds.DeviceSerialNumber = '25445'
|
|
111
|
-
ds.SoftwareVersions = 'syngo MR 2004V 4VB11D'
|
|
112
|
-
ds.ProtocolName = 'sag 3d gre +c'
|
|
113
|
-
ds.ContrastBolusVolume = '20.0'
|
|
114
|
-
ds.DateOfLastCalibration = '19031229'
|
|
115
|
-
ds.TimeOfLastCalibration = '155156.000000'
|
|
116
|
-
ds.TransmitCoilName = 'Body'
|
|
117
|
-
ds.InPlanePhaseEncodingDirection = 'ROW'
|
|
118
|
-
ds.FlipAngle = '20.0'
|
|
119
|
-
ds.VariableFlipAngleFlag = 'N'
|
|
120
|
-
ds.SAR = '0.09494107961655'
|
|
121
|
-
ds.dBdt = '0.0'
|
|
122
|
-
ds.PatientPosition = 'HFS'
|
|
123
|
-
ds.StudyInstanceUID = pydicom.uid.generate_uid()
|
|
124
|
-
ds.SeriesInstanceUID = pydicom.uid.generate_uid()
|
|
125
|
-
ds.StudyID = ''
|
|
126
|
-
ds.SeriesNumber = '14'
|
|
127
|
-
ds.AcquisitionNumber = '1'
|
|
128
|
-
ds.InstanceNumber = '1'
|
|
129
|
-
ds.ImagePositionPatient = [75.561665058136, -163.6216506958, 118.50172901154]
|
|
130
|
-
ds.ImageOrientationPatient = [0, 1, 0, 0, 0, -1]
|
|
131
|
-
ds.FrameOfReferenceUID = '1.3.6.1.4.1.9328.50.16.22344679587635360510174487884943834158'
|
|
132
|
-
ds.PositionReferenceIndicator = ''
|
|
133
|
-
ds.SliceLocation = '75.561665058136'
|
|
134
|
-
ds.SamplesPerPixel = 1
|
|
135
|
-
ds.PhotometricInterpretation = 'MONOCHROME2'
|
|
136
|
-
ds.Rows = 64
|
|
137
|
-
ds.Columns = 64
|
|
138
|
-
ds.PixelSpacing = [1, 1]
|
|
139
|
-
ds.BitsAllocated = 16
|
|
140
|
-
ds.BitsStored = 16
|
|
141
|
-
ds.HighBit = 15
|
|
142
|
-
ds.PixelRepresentation = 0
|
|
143
|
-
ds.SmallestImagePixelValue = 0
|
|
144
|
-
ds.LargestImagePixelValue = 913
|
|
145
|
-
ds.WindowCenter = '136.0'
|
|
146
|
-
ds.WindowWidth = '380.0'
|
|
147
|
-
ds.RescaleIntercept = '0.0'
|
|
148
|
-
ds.RescaleSlope = '1.0'
|
|
149
|
-
ds.RescaleType = 'PIXELVALUE'
|
|
150
|
-
ds.WindowCenterWidthExplanation = 'Algo1'
|
|
151
|
-
ds.RequestedProcedureDescription = 'MRI BRAIN W/WO ENHANCEMENT'
|
|
152
|
-
ds.ScheduledProcedureStepDescription = 'MRI BRAIN W/WO ENHANCEMENT'
|
|
153
|
-
ds.ScheduledProcedureStepID = '5133240'
|
|
154
|
-
ds.PerformedProcedureStepStartDate = '19040611'
|
|
155
|
-
ds.PerformedProcedureStepDescription = 'MRI BRAIN W/WO ENHANCEMENT'
|
|
156
|
-
ds.RequestAttributesSequence = Sequence()
|
|
157
|
-
ds.RequestedProcedureID = '5133240'
|
|
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)
|
|
160
|
-
|
|
161
|
-
return ds
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
def get_pixel_array(ds):
|
|
165
|
-
"""Read the pixel array from an MR image"""
|
|
166
|
-
|
|
167
|
-
#array = ds.pixel_array.astype(np.float64)
|
|
168
|
-
#array = ds.pixel_array
|
|
169
|
-
#array = np.frombuffer(ds.PixelData, dtype=np.uint16).reshape(ds.Rows, ds.Columns)
|
|
170
|
-
#array = array.astype(np.float32)
|
|
171
|
-
|
|
172
|
-
array = ds.pixel_array
|
|
173
|
-
array = array.astype(np.float32)
|
|
174
|
-
if [0x2005, 0x100E] in ds: # 'Philips Rescale Slope'
|
|
175
|
-
slope = ds[(0x2005, 0x100E)].value
|
|
176
|
-
intercept = ds[(0x2005, 0x100D)].value
|
|
177
|
-
array -= intercept
|
|
178
|
-
array /= slope
|
|
179
|
-
else:
|
|
180
|
-
slope = float(getattr(ds, 'RescaleSlope', 1))
|
|
181
|
-
intercept = float(getattr(ds, 'RescaleIntercept', 0))
|
|
182
|
-
array *= slope
|
|
183
|
-
array += intercept
|
|
184
|
-
return np.transpose(array)
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
def set_pixel_array(ds, array):
|
|
188
|
-
|
|
189
|
-
if (0x2005, 0x100E) in ds:
|
|
190
|
-
del ds[0x2005, 0x100E] # Delete 'Philips Rescale Slope'
|
|
191
|
-
if (0x2005, 0x100D) in ds:
|
|
192
|
-
del ds[0x2005, 0x100D]
|
|
193
|
-
|
|
194
|
-
# clipping may slow down a lot
|
|
195
|
-
array = image.clip(array.astype(np.float32))
|
|
196
|
-
array, slope, intercept = image.scale_to_range(array, ds.BitsAllocated)
|
|
197
|
-
array = np.transpose(array)
|
|
198
|
-
|
|
199
|
-
ds.PixelRepresentation = 0
|
|
200
|
-
ds.set_values('SmallestImagePixelValue', int(0))
|
|
201
|
-
ds.set_values('LargestImagePixelValue', int(2**ds.BitsAllocated - 1))
|
|
202
|
-
ds.RescaleSlope = 1 / slope
|
|
203
|
-
ds.RescaleIntercept = - intercept / slope
|
|
204
|
-
# ds.WindowCenter = (maximum + minimum) / 2
|
|
205
|
-
# ds.WindowWidth = maximum - minimum
|
|
206
|
-
ds.Rows = array.shape[0]
|
|
207
|
-
ds.Columns = array.shape[1]
|
|
208
|
-
ds.PixelData = array.tobytes()
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
def get_attribute_image_type(ds):
|
|
212
|
-
"""Determine if an image is Magnitude, Phase, Real or Imaginary image or None"""
|
|
213
|
-
|
|
214
|
-
if (0x0043, 0x102f) in ds:
|
|
215
|
-
private_ge = ds[0x0043, 0x102f]
|
|
216
|
-
try:
|
|
217
|
-
value = struct.unpack('h', private_ge.value)[0]
|
|
218
|
-
except:
|
|
219
|
-
value = private_ge.value
|
|
220
|
-
if value == 0:
|
|
221
|
-
return 'MAGNITUDE'
|
|
222
|
-
if value == 1:
|
|
223
|
-
return 'PHASE'
|
|
224
|
-
if value == 2:
|
|
225
|
-
return 'REAL'
|
|
226
|
-
if value == 3:
|
|
227
|
-
return 'IMAGINARY'
|
|
228
|
-
|
|
229
|
-
if 'ImageType' in ds:
|
|
230
|
-
type = set(ds.ImageType)
|
|
231
|
-
if set(['M', 'MAGNITUDE']).intersection(type):
|
|
232
|
-
return 'MAGNITUDE'
|
|
233
|
-
if set(['P', 'PHASE']).intersection(type):
|
|
234
|
-
return 'PHASE'
|
|
235
|
-
if set(['R', 'REAL']).intersection(type):
|
|
236
|
-
return 'REAL'
|
|
237
|
-
if set(['I', 'IMAGINARY']).intersection(type):
|
|
238
|
-
return 'IMAGINARY'
|
|
239
|
-
|
|
240
|
-
if 'ComplexImageComponent' in ds:
|
|
241
|
-
return ds.ComplexImageComponent
|
|
242
|
-
|
|
243
|
-
return 'UNKNOWN'
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
def set_attribute_image_type(ds, value):
|
|
247
|
-
ds.ImageType = value
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
def get_attribute_signal_type(ds):
|
|
251
|
-
"""Determine if an image is Water, Fat, In-Phase, Out-phase image or None"""
|
|
252
|
-
|
|
253
|
-
if hasattr(ds, 'ImageType'):
|
|
254
|
-
type = set(ds.ImageType)
|
|
255
|
-
if set(['W', 'WATER']).intersection(type):
|
|
256
|
-
return 'WATER'
|
|
257
|
-
elif set(['F', 'FAT']).intersection(type):
|
|
258
|
-
return 'FAT'
|
|
259
|
-
elif set(['IP', 'IN_PHASE']).intersection(type):
|
|
260
|
-
return 'IN_PHASE'
|
|
261
|
-
elif set(['OP', 'OUT_PHASE']).intersection(type):
|
|
262
|
-
return 'OP_PHASE'
|
|
263
|
-
return 'UNKNOWN'
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
def set_attribute_signal_type(ds, value):
|
|
267
|
-
ds.ImageType = value
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
"""Remnant code from old version - saved here for now"""
|
|
2
|
-
|
|
3
|
-
from pydicom.dataset import Dataset
|
|
4
|
-
import numpy as np
|
|
5
|
-
import datetime
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class ParametricMap(object):
|
|
10
|
-
def selectParametricMap(self, dicom, imageArray, argument):
|
|
11
|
-
methodName = argument
|
|
12
|
-
method = getattr(self, methodName, lambda: "No valid Parametric Map chosen")
|
|
13
|
-
return method(dicom, imageArray)
|
|
14
|
-
|
|
15
|
-
def RGB(self, dicom, imageArray):
|
|
16
|
-
dicom.PhotometricInterpretation = 'RGB'
|
|
17
|
-
dicom.SamplesPerPixel = 3
|
|
18
|
-
dicom.BitsAllocated = 8
|
|
19
|
-
dicom.BitsStored = 8
|
|
20
|
-
dicom.HighBit = 7
|
|
21
|
-
dicom.add_new(0x00280006, 'US', 0) # Planar Configuration
|
|
22
|
-
dicom.RescaleSlope = 1
|
|
23
|
-
dicom.RescaleIntercept = 0
|
|
24
|
-
pixelArray = imageArray.astype(np.uint8) # Should we multiply by 255?
|
|
25
|
-
dicom.WindowCenter = int((np.amax(imageArray) - np.amin(imageArray)) / 2)
|
|
26
|
-
dicom.WindowWidth = np.absolute(int(np.amax(imageArray) - np.amin(imageArray)))
|
|
27
|
-
dicom.PixelData = pixelArray.tobytes()
|
|
28
|
-
return
|
|
29
|
-
|
|
30
|
-
def ADC(self, dicom, imageArray):
|
|
31
|
-
# The commented parts are to apply when we decide to include Parametric Map IOD. No readers can deal with this yet
|
|
32
|
-
# dicom.SOPClassUID = '1.2.840.10008.5.1.4.1.1.67'
|
|
33
|
-
dicom.SeriesDescription = "Apparent Diffusion Coefficient (um2/s)"
|
|
34
|
-
dicom.Modality = "RWV"
|
|
35
|
-
dicom.FrameLaterality = "U"
|
|
36
|
-
dicom.DerivedPixelContrast = "ADC"
|
|
37
|
-
dicom.BitsAllocated = 32
|
|
38
|
-
dicom.PixelRepresentation = 1
|
|
39
|
-
dicom.PhotometricInterpretation = "MONOCHROME2"
|
|
40
|
-
dicom.PixelAspectRatio = ["1", "1"] # Need to have a better look at this
|
|
41
|
-
dicom.RescaleSlope = 1
|
|
42
|
-
dicom.RescaleIntercept = 0
|
|
43
|
-
# Rotate the image back to the original orientation
|
|
44
|
-
imageArray = np.transpose(imageArray)
|
|
45
|
-
dicom.Rows = np.shape(imageArray)[-2]
|
|
46
|
-
dicom.Columns = np.shape(imageArray)[-1]
|
|
47
|
-
dicom.WindowCenter = int((np.amax(imageArray) - np.amin(imageArray)) / 2)
|
|
48
|
-
dicom.WindowWidth = np.absolute(int(np.amax(imageArray) - np.amin(imageArray)))
|
|
49
|
-
dicom.FloatPixelData = bytes(imageArray.astype(np.float32).flatten())
|
|
50
|
-
del dicom.PixelData, dicom.BitsStored, dicom.HighBit
|
|
51
|
-
|
|
52
|
-
dicom.RealWorldValueMappingSequence = [Dataset(), Dataset(), Dataset(), Dataset()]
|
|
53
|
-
dicom.RealWorldValueMappingSequence[0].QuantityDefinitionSequence = [Dataset(), Dataset()]
|
|
54
|
-
dicom.RealWorldValueMappingSequence[0].QuantityDefinitionSequence[0].ValueType = "CODE"
|
|
55
|
-
dicom.RealWorldValueMappingSequence[0].QuantityDefinitionSequence[1].ConceptCodeSequence = [Dataset(), Dataset(), Dataset()]
|
|
56
|
-
dicom.RealWorldValueMappingSequence[0].QuantityDefinitionSequence[1].ConceptCodeSequence[0].CodeValue = "113041"
|
|
57
|
-
dicom.RealWorldValueMappingSequence[0].QuantityDefinitionSequence[1].ConceptCodeSequence[1].CodingSchemeDesignator = "DCM"
|
|
58
|
-
dicom.RealWorldValueMappingSequence[0].QuantityDefinitionSequence[1].ConceptCodeSequence[2].CodeMeaning = "Apparent Diffusion Coefficient"
|
|
59
|
-
dicom.RealWorldValueMappingSequence[1].MeasurementUnitsCodeSequence = [Dataset(), Dataset(), Dataset()]
|
|
60
|
-
dicom.RealWorldValueMappingSequence[1].MeasurementUnitsCodeSequence[0].CodeValue = "um2/s"
|
|
61
|
-
dicom.RealWorldValueMappingSequence[1].MeasurementUnitsCodeSequence[1].CodingSchemeDesignator = "UCUM"
|
|
62
|
-
dicom.RealWorldValueMappingSequence[1].MeasurementUnitsCodeSequence[2].CodeMeaning = "um2/s"
|
|
63
|
-
dicom.RealWorldValueMappingSequence[2].RealWorldValueSlope = 1
|
|
64
|
-
|
|
65
|
-
anatomyString = dicom.BodyPartExamined
|
|
66
|
-
saveAnatomicalInfo(anatomyString, dicom.RealWorldValueMappingSequence[3])
|
|
67
|
-
|
|
68
|
-
return
|
|
69
|
-
|
|
70
|
-
def T2Star(self, dicom, imageArray):
|
|
71
|
-
dicom.PixelSpacing = [3, 3] # find a mechanism to pass reconstruct pixel here
|
|
72
|
-
return
|
|
73
|
-
|
|
74
|
-
def SEG(self, dicom, imageArray):
|
|
75
|
-
#dicom.SOPClassUID = '1.2.840.10008.5.1.4.1.1.66.4' # WILL NOT BE USED HERE - This is for PACS. There will be another one for DICOM Standard
|
|
76
|
-
# The commented parts are to apply when we decide to include SEG IOD. No readers can deal with this yet
|
|
77
|
-
dicom.BitsAllocated = 8 # According to Federov DICOM Standard this should be 1-bit
|
|
78
|
-
dicom.BitsStored = 8
|
|
79
|
-
dicom.HighBit = 7
|
|
80
|
-
#dicom.SmallestImagePixelValue = 0
|
|
81
|
-
#dicom.LargestImagePixelValue = int(np.amax(imageArray)) # max 255
|
|
82
|
-
dicom.add_new('0x00280106', 'US', 0) # Minimum
|
|
83
|
-
dicom.add_new('0x00280107', 'US', int(np.amax(imageArray))) # Maximum
|
|
84
|
-
dicom.PixelRepresentation = 0
|
|
85
|
-
dicom.SamplesPerPixel = 1
|
|
86
|
-
#dicom.WindowCenter = 0.5
|
|
87
|
-
#dicom.WindowWidth = 1.1
|
|
88
|
-
dicom.add_new('0x00281050', 'DS', 0.5) # WindowCenter
|
|
89
|
-
dicom.add_new('0x00281051', 'DS', 1.1) # WindowWidth
|
|
90
|
-
#dicom.RescaleIntercept = 0
|
|
91
|
-
#dicom.RescaleSlope = 1
|
|
92
|
-
dicom.add_new('0x00281052', 'DS', 0) # RescaleIntercept
|
|
93
|
-
dicom.add_new('0x00281053', 'DS', 1) # RescaleSlope
|
|
94
|
-
dicom.LossyImageCompression = '00'
|
|
95
|
-
pixelArray = np.transpose(imageArray.astype(np.uint8)) # Should we multiply by 255?
|
|
96
|
-
dicom.PixelData = pixelArray.tobytes()
|
|
97
|
-
|
|
98
|
-
dicom.Modality = 'SEG'
|
|
99
|
-
dicom.SegmentationType = 'FRACTIONAL'
|
|
100
|
-
dicom.MaximumFractionalValue = int(np.amax(imageArray)) # max 255
|
|
101
|
-
dicom.SegmentationFractionalType = 'OCCUPANCY'
|
|
102
|
-
|
|
103
|
-
# Segment Labels
|
|
104
|
-
if hasattr(dicom, "ImageComments"):
|
|
105
|
-
dicom.ContentDescription = dicom.ImageComments.split('_')[-1] # 'Image segmentation'
|
|
106
|
-
segment_numbers = np.unique(pixelArray)
|
|
107
|
-
segment_dictionary = dict(list(enumerate(segment_numbers)))
|
|
108
|
-
segment_label = dicom.ImageComments.split('_')[-1]
|
|
109
|
-
segment_dictionary[0] = 'Background'
|
|
110
|
-
segment_dictionary[1] = segment_label
|
|
111
|
-
for key in segment_dictionary:
|
|
112
|
-
dicom.SegmentSequence = [Dataset(), Dataset(), Dataset(), Dataset(), Dataset(), Dataset()]
|
|
113
|
-
dicom.SegmentSequence[0].SegmentAlgorithmType = 'MANUAL'
|
|
114
|
-
dicom.SegmentSequence[1].SegmentNumber = key
|
|
115
|
-
dicom.SegmentSequence[2].SegmentDescription = str(segment_dictionary[key])
|
|
116
|
-
dicom.SegmentSequence[3].SegmentLabel = str(segment_dictionary[key])
|
|
117
|
-
dicom.SegmentSequence[4].SegmentAlgorithmName = "Weasel"
|
|
118
|
-
if hasattr(dicom, "BodyPartExamined"):
|
|
119
|
-
anatomyString = dicom.BodyPartExamined
|
|
120
|
-
saveAnatomicalInfo(anatomyString, dicom.SegmentSequence[5])
|
|
121
|
-
else:
|
|
122
|
-
dicom.ContentDescription = "Mask with no label"
|
|
123
|
-
|
|
124
|
-
return
|
|
125
|
-
|
|
126
|
-
def Registration(self, dicom, imageArray):
|
|
127
|
-
dicom.Modality = "REG"
|
|
128
|
-
return
|
|
129
|
-
|
|
130
|
-
def Signal(self, dicom, imageArray):
|
|
131
|
-
dicom.Modality = "RWV"
|
|
132
|
-
dicom.DerivedPixelContrast = "GraphPlot"
|
|
133
|
-
dicom.PhotometricInterpretation = "MONOCHROME2"
|
|
134
|
-
dicom.RescaleSlope = 1
|
|
135
|
-
dicom.RescaleIntercept = 0
|
|
136
|
-
imageArray = np.transpose(imageArray.astype(np.float32))
|
|
137
|
-
center = (np.amax(imageArray) + np.amin(imageArray)) / 2
|
|
138
|
-
width = np.amax(imageArray) - np.amin(imageArray)
|
|
139
|
-
dicom.add_new('0x00281050', 'DS', center)
|
|
140
|
-
dicom.add_new('0x00281051', 'DS', width)
|
|
141
|
-
dicom.BitsAllocated = 32
|
|
142
|
-
dicom.Rows = np.shape(imageArray)[0]
|
|
143
|
-
dicom.Columns = np.shape(imageArray)[1]
|
|
144
|
-
dicom.FloatPixelData = bytes(imageArray.flatten())
|
|
145
|
-
del dicom.PixelData, dicom.BitsStored, dicom.HighBit
|
|
146
|
-
return
|
|
147
|
-
|
|
148
|
-
# Could insert a method regarding ROI colours, like in ITK-SNAP???
|
|
149
|
-
def saveAnatomicalInfo(anatomyString, dicom):
|
|
150
|
-
try:
|
|
151
|
-
# FOR NOW, THE PRIORITY WILL BE ON KIDNEY
|
|
152
|
-
if "KIDNEY" or "ABDOMEN" in anatomyString.upper():
|
|
153
|
-
dicom.AnatomicRegionSequence = [Dataset(), Dataset(), Dataset()]
|
|
154
|
-
dicom.AnatomicRegionSequence[0].CodeValue = "T-71000"
|
|
155
|
-
dicom.AnatomicRegionSequence[1].CodingSchemeDesignator = "SRT"
|
|
156
|
-
dicom.AnatomicRegionSequence[2].CodeMeaning = "Kidney"
|
|
157
|
-
elif "LIVER" in anatomyString.upper():
|
|
158
|
-
dicom.AnatomicRegionSequence = [Dataset(), Dataset(), Dataset()]
|
|
159
|
-
dicom.AnatomicRegionSequence[0].CodeValue = "T-62000"
|
|
160
|
-
dicom.AnatomicRegionSequence[1].CodingSchemeDesignator = "SRT"
|
|
161
|
-
dicom.AnatomicRegionSequence[2].CodeMeaning = "Liver"
|
|
162
|
-
elif "PROSTATE" in anatomyString.upper():
|
|
163
|
-
dicom.AnatomicRegionSequence = [Dataset(), Dataset(), Dataset()]
|
|
164
|
-
dicom.AnatomicRegionSequence[0].CodeValue = "T-9200B"
|
|
165
|
-
dicom.AnatomicRegionSequence[1].CodingSchemeDesignator = "SRT"
|
|
166
|
-
dicom.AnatomicRegionSequence[2].CodeMeaning = "Prostate"
|
|
167
|
-
elif "BODY" in anatomyString.upper():
|
|
168
|
-
dicom.AnatomicRegionSequence = [Dataset(), Dataset(), Dataset()]
|
|
169
|
-
dicom.AnatomicRegionSequence[0].CodeValue = "P5-0905E"
|
|
170
|
-
dicom.AnatomicRegionSequence[1].CodingSchemeDesignator = "LN"
|
|
171
|
-
dicom.AnatomicRegionSequence[2].CodeMeaning = "MRI whole body"
|
|
172
|
-
except:
|
|
173
|
-
pass
|
|
174
|
-
return
|
|
175
|
-
|
|
176
|
-
def editDicom(newDicom, imageArray, parametricMap):
|
|
177
|
-
|
|
178
|
-
callCase = ParametricMap()
|
|
179
|
-
callCase.selectParametricMap(newDicom, imageArray, parametricMap)
|
|
180
|
-
|
|
181
|
-
dt = datetime.datetime.now()
|
|
182
|
-
timeStr = dt.strftime('%H%M%S') # long format with micro seconds
|
|
183
|
-
newDicom.PerformedProcedureStepStartDate = dt.strftime('%Y%m%d')
|
|
184
|
-
newDicom.PerformedProcedureStepStartTime = timeStr
|
|
185
|
-
newDicom.PerformedProcedureStepDescription = "Post-processing application"
|
|
186
|
-
|
|
187
|
-
return newDicom
|
|
188
|
-
|
|
189
|
-
# Series, Instance and Class for Reference
|
|
190
|
-
#newDicom.ReferencedSeriesSequence = [Dataset(), Dataset()]
|
|
191
|
-
#newDicom.ReferencedSeriesSequence[0].SeriesInstanceUID = dicom_data.SeriesInstanceUID
|
|
192
|
-
#newDicom.ReferencedSeriesSequence[1].ReferencedInstanceSequence = [Dataset(), Dataset()]
|
|
193
|
-
#newDicom.ReferencedSeriesSequence[1].ReferencedInstanceSequence[0].ReferencedSOPClassUID = dicom_data.SOPClassUID
|
|
194
|
-
#newDicom.ReferencedSeriesSequence[1].ReferencedInstanceSequence[1].ReferencedSOPInstanceUID = dicom_data.SOPInstanceUID
|
|
195
|
-
|
|
196
|
-
# rwv_sequence = Sequence()
|
|
197
|
-
# dicom.RealWorldValueMappingSequence = rwv_sequence
|
|
198
|
-
# rwv_slope = Dataset()
|
|
199
|
-
# rwv_slope.RealWorldValueSlope = 1
|
|
200
|
-
# rwv_sequence.append(rwv_slope)
|
|
201
|
-
|
|
202
|
-
# quantity_def = Dataset()
|
|
203
|
-
# quantity_def_sequence = Sequence()
|
|
204
|
-
# quantity_def.QuantityDefinitionSequence = quantity_def_sequence
|
|
205
|
-
# value_type = Dataset()
|
|
206
|
-
# value_type.ValueType = "CODE"
|
|
207
|
-
# quantity_def_sequence.append(value_type)
|
|
208
|
-
# concept_code = Dataset()
|
|
209
|
-
# concept_code_sequence = Sequence()
|
|
210
|
-
# concept_code.ConceptCodeSequence = concept_code_sequence
|
|
211
|
-
# code_code = Dataset()
|
|
212
|
-
# code_code.CodeValue = "113041"
|
|
213
|
-
# code_code.CodingSchemeDesignator = "DCM"
|
|
214
|
-
# code_code.CodeMeaning = "Apparent Diffusion Coefficient"
|
|
215
|
-
# concept_code_sequence.append(code_code)
|
|
216
|
-
# rwv_sequence.append(quantity_def)
|
|
217
|
-
|
|
218
|
-
# measure_units = Dataset()
|
|
219
|
-
# measure_units_sequence = Sequence()
|
|
220
|
-
# measure_units.MeasurementUnitsCodeSequence = measure_units_sequence
|
|
221
|
-
# measure_code = Dataset()
|
|
222
|
-
# measure_code.CodeValue = "um2/s"
|
|
223
|
-
# measure_code.CodingSchemeDesignator = "UCUM"
|
|
224
|
-
# measure_code.CodeMeaning = "um2/s"
|
|
225
|
-
# measure_units_sequence.append(measure_code)
|
|
226
|
-
# rwv_sequence.append(measure_units)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|