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
@@ -0,0 +1,310 @@
1
+ import numpy as np
2
+ import pydicom
3
+ from pydicom.dataset import Dataset, FileDataset
4
+ from pydicom.sequence import Sequence
5
+ from pydicom.uid import generate_uid, ParametricMapStorage
6
+ from datetime import datetime
7
+
8
+
9
+ def from_volume(vol):
10
+ pass
11
+
12
+
13
+ def create_parametric_map(rows=64, cols=64, frames=1):
14
+ # Create dummy pixel data (floating point)
15
+ pixel_array = np.random.rand(frames, rows, cols).astype(np.float32)
16
+
17
+ # File Meta Information
18
+ file_meta = Dataset()
19
+ file_meta.MediaStorageSOPClassUID = ParametricMapStorage
20
+ file_meta.MediaStorageSOPInstanceUID = generate_uid()
21
+ file_meta.ImplementationClassUID = generate_uid()
22
+
23
+ # Main Dataset
24
+ ds = FileDataset(None, {}, file_meta=file_meta, preamble=b"\0" * 128)
25
+
26
+ # Required UIDs
27
+ ds.SOPClassUID = ParametricMapStorage
28
+ ds.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID
29
+ ds.StudyInstanceUID = generate_uid()
30
+ ds.SeriesInstanceUID = generate_uid()
31
+ ds.FrameOfReferenceUID = generate_uid()
32
+
33
+ # Patient and Study
34
+ ds.PatientName = "Dummy^Patient"
35
+ ds.PatientID = "123456"
36
+ ds.StudyDate = datetime.now().strftime("%Y%m%d")
37
+ ds.StudyTime = datetime.now().strftime("%H%M%S")
38
+ ds.Modality = "OT"
39
+ ds.Manufacturer = "SyntheticGenerator"
40
+
41
+ # General Image
42
+ ds.SeriesNumber = 1
43
+ ds.InstanceNumber = 1
44
+
45
+ # Parametric Map specifics
46
+ ds.ImageType = ['DERIVED', 'PRIMARY']
47
+ ds.ContentLabel = "PMAP"
48
+ ds.ContentDescription = "Synthetic Parametric Map"
49
+ ds.ContentCreatorName = "OpenAI"
50
+
51
+ # Pixel Data
52
+ ds.Rows = rows
53
+ ds.Columns = cols
54
+ ds.NumberOfFrames = frames
55
+ ds.PixelData = pixel_array.tobytes()
56
+ ds.SamplesPerPixel = 1
57
+ ds.PhotometricInterpretation = "MONOCHROME2"
58
+ ds.BitsAllocated = 32
59
+ ds.BitsStored = 32
60
+ ds.HighBit = 31
61
+ ds.PixelRepresentation = 1 # 1 = signed, 0 = unsigned
62
+ ds.FloatPixelData = pixel_array.astype(np.float32).tobytes()
63
+ ds.PixelData = b"\0" * rows * cols * frames # Actual data goes in FloatPixelData
64
+
65
+ # Functional Group Sequences (minimal dummy values)
66
+ ds.SharedFunctionalGroupsSequence = [Dataset()]
67
+ ds.PerFrameFunctionalGroupsSequence = [Dataset() for _ in range(frames)]
68
+
69
+ # Add dummy Dimension Organization
70
+ ds.DimensionOrganizationSequence = [Dataset()]
71
+ ds.DimensionOrganizationSequence[0].DimensionOrganizationUID = generate_uid()
72
+
73
+ ds.DimensionIndexSequence = [
74
+ Dataset() for _ in range(1)
75
+ ]
76
+ ds.DimensionIndexSequence[0].DimensionOrganizationUID = ds.DimensionOrganizationSequence[0].DimensionOrganizationUID
77
+ ds.DimensionIndexSequence[0].DimensionIndexPointer = (0x0020, 0x9157) # In-stack position
78
+ ds.DimensionIndexSequence[0].FunctionalGroupPointer = (0x0020, 0x9116)
79
+
80
+ return ds
81
+
82
+
83
+
84
+
85
+ def create_int16_parametric_map_template(
86
+ rows=128, cols=128,
87
+ num_slices=10, num_custom1=5, num_custom2=3
88
+ ):
89
+ ds = FileDataset(None, {}, file_meta=Dataset(), preamble=b"\0" * 128)
90
+ ds.file_meta.TransferSyntaxUID = pydicom.uid.ExplicitVRLittleEndian
91
+ ds.is_little_endian = True
92
+ ds.is_implicit_VR = False
93
+
94
+ ds.SOPClassUID = '1.2.840.10008.5.1.4.1.1.30' # Parametric Map Storage
95
+ ds.SOPInstanceUID = pydicom.uid.generate_uid()
96
+ ds.Modality = 'OT'
97
+ ds.PatientName = 'Integer^Patient'
98
+ ds.PatientID = 'INT001'
99
+
100
+ ds.Rows = rows
101
+ ds.Columns = cols
102
+ num_frames = num_slices * num_custom1 * num_custom2
103
+ ds.NumberOfFrames = str(num_frames)
104
+
105
+ # Image pixel properties for int16
106
+ ds.PhotometricInterpretation = "MONOCHROME2"
107
+ ds.SamplesPerPixel = 1
108
+ ds.BitsAllocated = 16
109
+ ds.BitsStored = 16
110
+ ds.HighBit = 15
111
+ ds.PixelRepresentation = 1 # 1 = signed integer
112
+
113
+ # Date/time
114
+ dt = datetime.datetime.now()
115
+ ds.ContentDate = dt.strftime('%Y%m%d')
116
+ ds.ContentTime = dt.strftime('%H%M%S.%f')[:13]
117
+
118
+ # Dimension Organization
119
+ dim_org = Dataset()
120
+ dim_org.DimensionOrganizationUID = pydicom.uid.generate_uid()
121
+ ds.DimensionOrganizationSequence = Sequence([dim_org])
122
+
123
+ # Dimension Index Sequence
124
+ dim_index_seq = []
125
+
126
+ d1 = Dataset()
127
+ d1.DimensionIndexPointer = 0x00200032 # ImagePositionPatient
128
+ d1.DimensionDescriptionLabel = 'SliceLocation'
129
+ dim_index_seq.append(d1)
130
+
131
+ d2 = Dataset()
132
+ d2.DimensionIndexPointer = (0x0011, 0x1010)
133
+ d2.DimensionDescriptionLabel = 'CustomDim1'
134
+ dim_index_seq.append(d2)
135
+
136
+ d3 = Dataset()
137
+ d3.DimensionIndexPointer = (0x0011, 0x1020)
138
+ d3.DimensionDescriptionLabel = 'CustomDim2'
139
+ dim_index_seq.append(d3)
140
+
141
+ ds.DimensionIndexSequence = Sequence(dim_index_seq)
142
+
143
+ # Shared Functional Groups
144
+ shared_fg = Dataset()
145
+
146
+ pm = Dataset()
147
+ pm.PixelSpacing = [1.0, 1.0]
148
+ pm.SliceThickness = 1.0
149
+ shared_fg.PixelMeasuresSequence = Sequence([pm])
150
+
151
+ po = Dataset()
152
+ po.ImageOrientationPatient = [1, 0, 0, 0, 1, 0]
153
+ shared_fg.PlaneOrientationSequence = Sequence([po])
154
+
155
+ ds.SharedFunctionalGroupsSequence = Sequence([shared_fg])
156
+
157
+ # Per Frame Functional Groups Sequence
158
+ per_frame_seq = []
159
+ for slice_idx in range(num_slices):
160
+ for custom1_idx in range(num_custom1):
161
+ for custom2_idx in range(num_custom2):
162
+ fg = Dataset()
163
+
164
+ # Plane Position Sequence
165
+ pp = Dataset()
166
+ pp.ImagePositionPatient = [0.0, 0.0, float(slice_idx * 5)]
167
+ fg.PlanePositionSequence = Sequence([pp])
168
+
169
+ # Custom dimension values (private tags)
170
+ fg.add_new((0x0011, 0x1010), 'LO', str(custom1_idx))
171
+ fg.add_new((0x0011, 0x1020), 'LO', str(custom2_idx))
172
+
173
+ per_frame_seq.append(fg)
174
+
175
+ ds.PerFrameFunctionalGroupsSequence = Sequence(per_frame_seq)
176
+
177
+ # Create int16 pixel data (dummy values)
178
+ pixel_array = np.zeros((num_frames, rows, cols), dtype=np.int16)
179
+ ds.PixelData = pixel_array.tobytes()
180
+
181
+ # Optional: Real World Value Mapping (for scaled physical interpretation)
182
+ rwvm = Dataset()
183
+ rwvm.RealWorldValueIntercept = 0.0 # to convert stored values to real-world values
184
+ rwvm.RealWorldValueSlope = 1.0
185
+ rwvm.LUTLabel = 'IntegerMap' # "T1_Mapping", "Perfusion", etc
186
+ unit_code = Dataset()
187
+ unit_code.CodeValue = 'kPa'
188
+ unit_code.CodingSchemeDesignator = 'UCUM'
189
+ unit_code.CodeMeaning = 'kilopascal'
190
+ rwvm.MeasurementUnitsCodeSequence = Sequence([unit_code])
191
+ ds.RealWorldValueMappingSequence = Sequence([rwvm])
192
+
193
+ return ds
194
+
195
+
196
+
197
+
198
+
199
+ def create_float32_parametric_map_template(
200
+ rows=128, cols=128,
201
+ num_slices=10, num_custom1=5, num_custom2=3
202
+ ):
203
+ ds = FileDataset(None, {}, file_meta=Dataset(), preamble=b"\0" * 128)
204
+ ds.file_meta.TransferSyntaxUID = pydicom.uid.ExplicitVRLittleEndian
205
+ ds.is_little_endian = True
206
+ ds.is_implicit_VR = False
207
+
208
+ ds.SOPClassUID = '1.2.840.10008.5.1.4.1.1.30' # Parametric Map Storage
209
+ ds.SOPInstanceUID = pydicom.uid.generate_uid()
210
+ ds.Modality = 'OT'
211
+ ds.PatientName = 'Float^Patient'
212
+ ds.PatientID = 'FLOAT001'
213
+
214
+ ds.Rows = rows
215
+ ds.Columns = cols
216
+ num_frames = num_slices * num_custom1 * num_custom2
217
+ ds.NumberOfFrames = str(num_frames)
218
+
219
+ # Image pixel properties for float32
220
+ ds.PhotometricInterpretation = "MONOCHROME2"
221
+ ds.SamplesPerPixel = 1
222
+ ds.BitsAllocated = 32
223
+ ds.BitsStored = 32
224
+ ds.HighBit = 31
225
+ ds.PixelRepresentation = 0 # 0 = unsigned (for float32)
226
+
227
+ # Date/time
228
+ dt = datetime.datetime.now()
229
+ ds.ContentDate = dt.strftime('%Y%m%d')
230
+ ds.ContentTime = dt.strftime('%H%M%S.%f')[:13]
231
+
232
+ # Dimension Organization
233
+ dim_org = Dataset()
234
+ dim_org.DimensionOrganizationUID = pydicom.uid.generate_uid()
235
+ ds.DimensionOrganizationSequence = Sequence([dim_org])
236
+
237
+ # Dimension Index Sequence
238
+ dim_index_seq = []
239
+
240
+ d1 = Dataset()
241
+ d1.DimensionIndexPointer = 0x00200032 # ImagePositionPatient
242
+ d1.DimensionDescriptionLabel = 'SliceLocation'
243
+ dim_index_seq.append(d1)
244
+
245
+ d2 = Dataset()
246
+ d2.DimensionIndexPointer = (0x0011, 0x1010)
247
+ d2.DimensionDescriptionLabel = 'CustomDim1'
248
+ dim_index_seq.append(d2)
249
+
250
+ d3 = Dataset()
251
+ d3.DimensionIndexPointer = (0x0011, 0x1020)
252
+ d3.DimensionDescriptionLabel = 'CustomDim2'
253
+ dim_index_seq.append(d3)
254
+
255
+ ds.DimensionIndexSequence = Sequence(dim_index_seq)
256
+
257
+ # Shared Functional Groups
258
+ shared_fg = Dataset()
259
+
260
+ pm = Dataset()
261
+ pm.PixelSpacing = [1.0, 1.0]
262
+ pm.SliceThickness = 1.0
263
+ shared_fg.PixelMeasuresSequence = Sequence([pm])
264
+
265
+ po = Dataset()
266
+ po.ImageOrientationPatient = [1, 0, 0, 0, 1, 0]
267
+ shared_fg.PlaneOrientationSequence = Sequence([po])
268
+
269
+ ds.SharedFunctionalGroupsSequence = Sequence([shared_fg])
270
+
271
+ # Per Frame Functional Groups Sequence
272
+ per_frame_seq = []
273
+ for slice_idx in range(num_slices):
274
+ for custom1_idx in range(num_custom1):
275
+ for custom2_idx in range(num_custom2):
276
+ fg = Dataset()
277
+
278
+ # Plane Position Sequence
279
+ pp = Dataset()
280
+ pp.ImagePositionPatient = [0.0, 0.0, float(slice_idx * 5)]
281
+ fg.PlanePositionSequence = Sequence([pp])
282
+
283
+ # Custom dimension values (private tags)
284
+ fg.add_new((0x0011, 0x1010), 'LO', str(custom1_idx))
285
+ fg.add_new((0x0011, 0x1020), 'LO', str(custom2_idx))
286
+
287
+ per_frame_seq.append(fg)
288
+
289
+ ds.PerFrameFunctionalGroupsSequence = Sequence(per_frame_seq)
290
+
291
+ # Create float32 pixel data (dummy)
292
+ pixel_array = np.zeros((num_frames, rows, cols), dtype=np.float32)
293
+ ds.PixelData = pixel_array.tobytes()
294
+
295
+ # Optional: Real World Value Mapping
296
+ rwvm = Dataset()
297
+ rwvm.RealWorldValueIntercept = 0.0
298
+ rwvm.RealWorldValueSlope = 1.0
299
+ rwvm.LUTLabel = 'FloatMap'
300
+ unit_code = Dataset()
301
+ unit_code.CodeValue = '1'
302
+ unit_code.CodingSchemeDesignator = 'UCUM'
303
+ unit_code.CodeMeaning = 'no units'
304
+ rwvm.MeasurementUnitsCodeSequence = Sequence([unit_code])
305
+ ds.RealWorldValueMappingSequence = Sequence([rwvm])
306
+
307
+ return ds
308
+
309
+
310
+
@@ -0,0 +1,140 @@
1
+ import numpy as np
2
+ import pydicom
3
+ from pydicom.dataset import Dataset, FileDataset, FileMetaDataset
4
+ from pydicom.uid import SecondaryCaptureImageStorage, generate_uid, ExplicitVRLittleEndian
5
+ from datetime import datetime
6
+ from pydicom.sequence import Sequence
7
+
8
+
9
+
10
+ def create_3d_secondary_capture_dataset_with_dimensions(depth=16, rows=256, cols=256, pixel_volume=None):
11
+ now = datetime.now()
12
+
13
+ # File Meta
14
+ file_meta = FileMetaDataset()
15
+ file_meta.MediaStorageSOPClassUID = SecondaryCaptureImageStorage
16
+ file_meta.MediaStorageSOPInstanceUID = generate_uid()
17
+ file_meta.ImplementationClassUID = generate_uid()
18
+ file_meta.TransferSyntaxUID = ExplicitVRLittleEndian
19
+
20
+ # Dataset
21
+ ds = FileDataset(None, {}, file_meta=file_meta, preamble=b"\0" * 128)
22
+ ds.is_little_endian = True
23
+ ds.is_implicit_VR = False
24
+
25
+ # Patient & Study Info
26
+ ds.PatientName = "SC^ThreeD"
27
+ ds.PatientID = "3D123456"
28
+ ds.StudyInstanceUID = generate_uid()
29
+ ds.SeriesInstanceUID = generate_uid()
30
+ ds.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID
31
+ ds.SOPClassUID = SecondaryCaptureImageStorage
32
+ ds.StudyDate = now.strftime("%Y%m%d")
33
+ ds.StudyTime = now.strftime("%H%M%S")
34
+ ds.Modality = "OT"
35
+ ds.Manufacturer = "PythonSC"
36
+
37
+ ds.SeriesNumber = 1
38
+ ds.InstanceNumber = 1
39
+
40
+ # Image Attributes
41
+ ds.SamplesPerPixel = 1
42
+ ds.PhotometricInterpretation = "MONOCHROME2"
43
+ ds.Rows = rows
44
+ ds.Columns = cols
45
+ ds.BitsAllocated = 16
46
+ ds.BitsStored = 12
47
+ ds.HighBit = 11
48
+ ds.PixelRepresentation = 0
49
+ ds.NumberOfFrames = str(depth)
50
+ ds.ImageType = ["DERIVED", "SECONDARY"]
51
+
52
+ # Pixel Data
53
+ if pixel_volume is None:
54
+ pixel_volume = np.random.randint(0, 4095, size=(depth, rows, cols), dtype=np.uint16)
55
+ ds.PixelData = pixel_volume.tobytes()
56
+
57
+ # === DIMENSIONS ===
58
+ dim_uid = generate_uid()
59
+
60
+ ds.DimensionOrganizationSequence = Sequence([
61
+ Dataset()
62
+ ])
63
+ ds.DimensionOrganizationSequence[0].DimensionOrganizationUID = dim_uid
64
+
65
+ # Define 1 dimension: slice index (z-dimension)
66
+ dim_index = Dataset()
67
+ dim_index.DimensionOrganizationUID = dim_uid
68
+ dim_index.DimensionIndexPointer = 0x00200032 # ImagePositionPatient
69
+ dim_index.FunctionalGroupPointer = 0x00209113 # PlanePositionSequence
70
+
71
+ ds.DimensionIndexSequence = Sequence([dim_index])
72
+
73
+ # Per-Frame Functional Groups
74
+ ds.PerFrameFunctionalGroupsSequence = Sequence()
75
+
76
+ for z in range(depth):
77
+ frame = Dataset()
78
+
79
+ # Plane position sequence with slice position
80
+ pos = Dataset()
81
+ pos.ImagePositionPatient = [0.0, 0.0, float(z)] # Simple linear z spacing
82
+ frame.PlanePositionSequence = Sequence([pos])
83
+
84
+ ds.PerFrameFunctionalGroupsSequence.append(frame)
85
+
86
+ return ds
87
+
88
+
89
+
90
+ def create_3d_secondary_capture_dataset(depth=16, rows=256, cols=256, pixel_volume=None):
91
+ now = datetime.now()
92
+ total_frames = depth
93
+
94
+ # File Meta
95
+ file_meta = pydicom.dataset.FileMetaDataset()
96
+ file_meta.MediaStorageSOPClassUID = SecondaryCaptureImageStorage
97
+ file_meta.MediaStorageSOPInstanceUID = generate_uid()
98
+ file_meta.ImplementationClassUID = generate_uid()
99
+ file_meta.TransferSyntaxUID = ExplicitVRLittleEndian
100
+
101
+ # FileDataset
102
+ ds = FileDataset(None, {}, file_meta=file_meta, preamble=b"\0" * 128)
103
+ ds.is_little_endian = True
104
+ ds.is_implicit_VR = False
105
+
106
+ # Basic metadata
107
+ ds.SOPClassUID = SecondaryCaptureImageStorage
108
+ ds.SOPInstanceUID = file_meta.MediaStorageSOPInstanceUID
109
+ ds.PatientName = "SC^ThreeD"
110
+ ds.PatientID = "3D123456"
111
+ ds.StudyInstanceUID = generate_uid()
112
+ ds.SeriesInstanceUID = generate_uid()
113
+ ds.StudyDate = now.strftime("%Y%m%d")
114
+ ds.StudyTime = now.strftime("%H%M%S")
115
+ ds.Modality = "OT"
116
+ ds.Manufacturer = "PythonGenerator"
117
+
118
+ ds.SeriesNumber = 1
119
+ ds.InstanceNumber = 1
120
+
121
+ # Image attributes
122
+ ds.SamplesPerPixel = 1
123
+ ds.PhotometricInterpretation = "MONOCHROME2"
124
+ ds.Rows = rows
125
+ ds.Columns = cols
126
+ ds.BitsAllocated = 16
127
+ ds.BitsStored = 12
128
+ ds.HighBit = 11
129
+ ds.PixelRepresentation = 0
130
+ ds.NumberOfFrames = str(total_frames)
131
+ ds.ImageType = ["DERIVED", "SECONDARY"]
132
+
133
+ # Dummy or real 3D pixel data
134
+ if pixel_volume is None:
135
+ pixel_volume = np.random.randint(0, 4095, size=(depth, rows, cols), dtype=np.uint16)
136
+
137
+ ds.PixelData = pixel_volume.tobytes()
138
+
139
+ return ds
140
+