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