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
@@ -1,503 +0,0 @@
1
- # pip install SimpleITK-SimpleElastix
2
-
3
- import numpy as np
4
- import itk
5
- from skimage.measure import block_reduce
6
- from dbdicom.extensions import vreg
7
-
8
-
9
- def coregister_3d_to_3d(moving, fixed,
10
- transformation = 'Affine',
11
- metric = "NormalizedMutualInformation",
12
- final_grid_spacing = 1.0,
13
- apply_to = []):
14
-
15
- background = 2**16-1
16
- fixed_map = vreg.map_to(fixed, moving, cval=background)
17
-
18
- # Get arrays for fixed and moving series
19
- array_fixed, _ = fixed_map.array('SliceLocation', pixels_first=True, first_volume=True)
20
- array_moving, headers_moving = moving.array('SliceLocation', pixels_first=True, first_volume=True)
21
-
22
- # Remove temporary overlay
23
- if fixed_map != fixed:
24
- fixed_map.remove()
25
-
26
- # Set background pixels to zero for both images
27
- idx = np.where(array_fixed==background)
28
- array_fixed[idx] = 0
29
- array_moving[idx] = 0
30
-
31
- # Apply coregistration settings
32
- moving.message('Preparing coregistration..')
33
- if transformation == 'Rigid':
34
- pars = _default_rigid('3')
35
- elif transformation == 'Affine':
36
- pars = _default_affine('3')
37
- else:
38
- pars = _default_bspline('3')
39
- pars.SetParameter("Metric", metric)
40
- pars.SetParameter("FinalGridSpacingInPhysicalUnits", str(final_grid_spacing))
41
-
42
- # Get slice spacing
43
- slice_spacing = headers_moving[0].SpacingBetweenSlices
44
- if slice_spacing is None:
45
- slice_spacing = headers_moving[0].SliceThickness
46
- pixel_spacing = headers_moving[0].PixelSpacing + [slice_spacing]
47
-
48
- # Coregister and save as DICOM
49
- coregistered, params = _coregister_arrays_3d(
50
- array_fixed, array_moving,
51
- pars, pixel_spacing,
52
- return_deformation_field=False)
53
- coreg = moving.new_sibling(suffix='coreg')
54
- coreg.set_array(coregistered, headers_moving, pixels_first=True)
55
-
56
- # Apply the transformation to other series
57
- apply_to_coreg = []
58
- for s, series in enumerate(apply_to):
59
- moving.progress(s+1, len(apply_to), 'Applying transformation..')
60
- array, headers = series.array('SliceLocation', pixels_first=True, first_volume=True)
61
- if array.shape != array_moving.shape:
62
- msg = 'Cannot apply the same transformation to other series with a different shape'
63
- raise ValueError(msg)
64
- array = _apply_3d_transformation(array, params, pixel_spacing)
65
- new = series.new_sibling(suffix='coreg')
66
- new.set_array(array, headers, pixels_first=True)
67
- apply_to_coreg.append(new)
68
-
69
- return coreg, apply_to_coreg
70
-
71
-
72
-
73
-
74
- def coregister_2d_to_2d(moving, fixed,
75
- transformation = 'Affine',
76
- metric = "NormalizedMutualInformation",
77
- final_grid_spacing = 1.0,
78
- ):
79
-
80
- background = 2**16-1
81
- fixed_map = vreg.map_to(fixed, moving, cval=background)
82
-
83
- # Get arrays for fixed and moving series
84
- array_fixed, _ = fixed_map.array('SliceLocation', pixels_first=True, first_volume=True)
85
- array_moving, headers_moving = moving.array('SliceLocation', pixels_first=True, first_volume=True)
86
-
87
- # Remove temporary overlay
88
- if fixed_map != fixed:
89
- fixed_map.remove()
90
-
91
- # Set background pixels to zero for both images
92
- idx = np.where(array_fixed==background)
93
- array_fixed[idx] = 0
94
- array_moving[idx] = 0
95
-
96
- # Get coregistration settings
97
- moving.message('Setting up coregistration..')
98
- if transformation == 'Rigid':
99
- pars = _default_rigid('2')
100
- elif transformation == 'Affine':
101
- pars = _default_affine('2')
102
- else:
103
- pars = _default_bspline('2')
104
- pars.SetParameter("Metric", metric)
105
- pars.SetParameter("FinalGridSpacingInPhysicalUnits", str(final_grid_spacing))
106
-
107
- # Coregister fixed and moving slice-by-slice
108
- pixel_spacing = headers_moving[0].PixelSpacing
109
- for z in range(array_moving.shape[2]):
110
- moving.status.progress(z+1, array_moving.shape[2], 'Performing coregistration..')
111
- coreg = _coregister_arrays(array_fixed[:,:,z], array_moving[:,:,z], pars, pixel_spacing, return_deformation_field=False)
112
- array_moving[:,:,z] = coreg
113
-
114
- # Save as DICOM
115
- coreg = moving.new_sibling(suffix='coregistered')
116
- coreg.set_array(array_moving, headers_moving, pixels_first=True)
117
- return coreg
118
-
119
-
120
-
121
-
122
-
123
- # BELOW HERE NON-DICOM FUNCTIONALITY
124
-
125
-
126
-
127
-
128
- # 3D version does not have the downsampling option
129
- # some bug involving the image shaping
130
- def _coregister_arrays_3d(
131
- target, source,
132
- elastix_model_parameters,
133
- spacing,
134
- log=False,
135
- return_deformation_field=False):
136
-
137
- # Convert to itk images
138
- source = itk.GetImageFromArray(np.array(source, np.float32))
139
- target = itk.GetImageFromArray(np.array(target, np.float32))
140
- source.SetSpacing(spacing)
141
- target.SetSpacing(spacing)
142
-
143
- # Coregister source to target
144
- coreg, result_transform_parameters = itk.elastix_registration_method(
145
- target, source,
146
- parameter_object=elastix_model_parameters,
147
- log_to_console=log)
148
- coreg = itk.GetArrayFromImage(coreg)
149
-
150
- if not return_deformation_field:
151
- return coreg, result_transform_parameters
152
-
153
- # Get deformation field
154
- deformation_field = itk.transformix_deformation_field(
155
- target, result_transform_parameters,
156
- log_to_console=log)
157
- deformation_field = itk.GetArrayFromImage(deformation_field)
158
- return coreg, result_transform_parameters, deformation_field
159
-
160
-
161
- def _apply_3d_transformation(
162
- source, result_transform_parameters,
163
- spacing, log=False):
164
-
165
- source = itk.GetImageFromArray(np.array(source, np.float32))
166
- source.SetSpacing(spacing)
167
- coreg = itk.transformix_filter(
168
- source, result_transform_parameters,
169
- log_to_console=log)
170
- return itk.GetArrayFromImage(coreg)
171
-
172
-
173
-
174
-
175
- def _coregister_arrays(
176
- target_large,
177
- source_large,
178
- elastix_model_parameters,
179
- spacing_large,
180
- log=False,
181
- downsample:int=1,
182
- return_deformation_field=False):
183
-
184
- # Downsample source and target
185
- # The origin of an image is the center of the voxel in the lower left corner
186
- # The origin of the large image is (0,0).
187
- # The original of the small image is therefore:
188
- # spacing_large/2 + (spacing_small/2 - spacing_large)
189
- # = (spacing_small - spacing_large)/2
190
- target_small = block_reduce(target_large, block_size=downsample, func=np.mean)
191
- source_small = block_reduce(source_large, block_size=downsample, func=np.mean)
192
- spacing_small = [spacing*downsample for spacing in spacing_large]
193
- origin_large = [0] * len(spacing_large)
194
- origin_small = [(spacing_small[i] - spacing_large[i])/2 for i in range(len(spacing_small))]
195
-
196
- # Coregister downsampled source to target
197
- source_small = itk.GetImageFromArray(np.array(source_small, np.float32))
198
- target_small = itk.GetImageFromArray(np.array(target_small, np.float32))
199
- source_small.SetSpacing(spacing_small)
200
- target_small.SetSpacing(spacing_small)
201
- source_small.SetOrigin(origin_small)
202
- target_small.SetOrigin(origin_small)
203
- coreg_small, result_transform_parameters = itk.elastix_registration_method(
204
- target_small, source_small,
205
- parameter_object=elastix_model_parameters,
206
- log_to_console=log)
207
-
208
- # Get coregistered image at original size
209
- result_transform_parameters.SetParameter(0, "Size", [str(dim) for dim in source_large.shape])
210
- result_transform_parameters.SetParameter(0, "Spacing", [str(dim) for dim in spacing_large])
211
- source_large = itk.GetImageFromArray(np.array(source_large, np.float32))
212
- source_large.SetSpacing(spacing_large)
213
- source_large.SetOrigin(origin_large)
214
- coreg_large = itk.transformix_filter(
215
- source_large,
216
- result_transform_parameters,
217
- log_to_console=log)
218
- coreg_large = itk.GetArrayFromImage(coreg_large)
219
- if coreg_large.ndim==3:
220
- coreg_large = np.transpose(coreg_large, (1,2,0))
221
-
222
- if not return_deformation_field:
223
- return coreg_large
224
-
225
- # Get deformation field at original size
226
- target_large = itk.GetImageFromArray(np.array(target_large, np.float32))
227
- target_large.SetSpacing(spacing_large)
228
- target_large.SetOrigin(origin_large)
229
- deformation_field = itk.transformix_deformation_field(
230
- target_large,
231
- result_transform_parameters,
232
- log_to_console=log)
233
- deformation_field = itk.GetArrayFromImage(deformation_field)
234
- if deformation_field.ndim==4:
235
- deformation_field = np.transpose(deformation_field, (1,2,0,3))
236
- else:
237
- deformation_field = np.reshape(deformation_field, target_large.shape + (len(target_large.shape), ))
238
- return coreg_large, deformation_field
239
-
240
-
241
- def _default_bspline(d):
242
- param_obj = itk.ParameterObject.New()
243
- parameter_map_bspline = param_obj.GetDefaultParameterMap('bspline')
244
- ## add parameter map file to the parameter object: required in itk-elastix
245
- param_obj.AddParameterMap(parameter_map_bspline)
246
- #OPTIONAL: Write the default parameter file to output file
247
- # param_obj.WriteParameterFile(parameter_map_bspline, "bspline.default.txt")
248
- # *********************
249
- # * ImageTypes
250
- # *********************
251
- param_obj.SetParameter("FixedInternalImagePixelType", "float")
252
- param_obj.SetParameter("MovingInternalImagePixelType", "float")
253
- ## selection based on 3D or 2D image data: newest elastix version does not require input image dimension
254
- param_obj.SetParameter("FixedImageDimension", d)
255
- param_obj.SetParameter("MovingImageDimension", d)
256
- param_obj.SetParameter("UseDirectionCosines", "true")
257
- # *********************
258
- # * Components
259
- # *********************
260
- param_obj.SetParameter("Registration", "MultiResolutionRegistration")
261
- # Image intensities are sampled using an ImageSampler, Interpolator and ResampleInterpolator.
262
- # Image sampler is responsible for selecting points in the image to sample.
263
- # The RandomCoordinate simply selects random positions.
264
- param_obj.SetParameter("ImageSampler", "RandomCoordinate")
265
- # Interpolator is responsible for interpolating off-grid positions during optimization.
266
- # The BSplineInterpolator with BSplineInterpolationOrder = 1 used here is very fast and uses very little memory
267
- param_obj.SetParameter("Interpolator", "BSplineInterpolator")
268
- # ResampleInterpolator here chosen to be FinalBSplineInterpolator with FinalBSplineInterpolationOrder = 1
269
- # is used to resample the result image from the moving image once the final transformation has been found.
270
- # This is a one-time step so the additional computational complexity is worth the trade-off for higher image quality.
271
- param_obj.SetParameter("ResampleInterpolator", "FinalBSplineInterpolator")
272
- param_obj.SetParameter("Resampler", "DefaultResampler")
273
- # Order of B-Spline interpolation used during registration/optimisation.
274
- # It may improve accuracy if you set this to 3. Never use 0.
275
- # An order of 1 gives linear interpolation. This is in most
276
- # applications a good choice.
277
- param_obj.SetParameter("BSplineInterpolationOrder", "1")
278
- # Order of B-Spline interpolation used for applying the final
279
- # deformation.
280
- # 3 gives good accuracy; recommended in most cases.
281
- # 1 gives worse accuracy (linear interpolation)
282
- # 0 gives worst accuracy, but is appropriate for binary images
283
- # (masks, segmentations); equivalent to nearest neighbor interpolation.
284
- param_obj.SetParameter("FinalBSplineInterpolationOrder", "3")
285
- # Pyramids found in Elastix:
286
- # 1) Smoothing -> Smoothing: YES, Downsampling: NO
287
- # 2) Recursive -> Smoothing: YES, Downsampling: YES
288
- # If Recursive is chosen and only # of resolutions is given
289
- # then downsamlping by a factor of 2 (default)
290
- # 3) Shrinking -> Smoothing: NO, Downsampling: YES
291
- param_obj.SetParameter("FixedImagePyramid", "FixedSmoothingImagePyramid")
292
- param_obj.SetParameter("MovingImagePyramid", "MovingSmoothingImagePyramid")
293
- param_obj.SetParameter("Optimizer", "AdaptiveStochasticGradientDescent")
294
- # Whether transforms are combined by composition or by addition.
295
- # In generally, Compose is the best option in most cases.
296
- # It does not influence the results very much.
297
- param_obj.SetParameter("HowToCombineTransforms", "Compose")
298
- param_obj.SetParameter("Transform", "BSplineTransform")
299
- # Metric
300
- param_obj.SetParameter("Metric", "NormalizedMutualInformation")
301
- # Number of grey level bins in each resolution level,
302
- # for the mutual information. 16 or 32 usually works fine.
303
- # You could also employ a hierarchical strategy:
304
- #(NumberOfHistogramBins 16 32 64)
305
- param_obj.SetParameter("NumberOfHistogramBins", "32")
306
- # *********************
307
- # * Transformation
308
- # *********************
309
- # The control point spacing of the bspline transformation in
310
- # the finest resolution level. Can be specified for each
311
- # dimension differently. Unit: mm.
312
- # The lower this value, the more flexible the deformation.
313
- # Low values may improve the accuracy, but may also cause
314
- # unrealistic deformations.
315
- # By default the grid spacing is halved after every resolution,
316
- # such that the final grid spacing is obtained in the last
317
- # resolution level.
318
- # The grid spacing here is specified in voxel units.
319
- #(FinalGridSpacingInPhysicalUnits 10.0 10.0)
320
- #(FinalGridSpacingInVoxels 8)
321
- #param_obj.SetParameter("FinalGridSpacingInPhysicalUnits", ["50.0", "50.0"])
322
- param_obj.SetParameter("FinalGridSpacingInPhysicalUnits", "25.0")
323
- # *********************
324
- # * Optimizer settings
325
- # *********************
326
- # The number of resolutions. 1 Is only enough if the expected
327
- # deformations are small. 3 or 4 mostly works fine. For large
328
- # images and large deformations, 5 or 6 may even be useful.
329
- param_obj.SetParameter("NumberOfResolutions", "4")
330
- param_obj.SetParameter("AutomaticParameterEstimation", "true")
331
- param_obj.SetParameter("ASGDParameterEstimationMethod", "Original")
332
- param_obj.SetParameter("MaximumNumberOfIterations", "500")
333
- # The step size of the optimizer, in mm. By default the voxel size is used.
334
- # which usually works well. In case of unusual high-resolution images
335
- # (eg histology) it is necessary to increase this value a bit, to the size
336
- # of the "smallest visible structure" in the image:
337
- param_obj.SetParameter("MaximumStepLength", "0.1")
338
- # *********************
339
- # * Pyramid settings
340
- # *********************
341
- # The downsampling/blurring factors for the image pyramids.
342
- # By default, the images are downsampled by a factor of 2
343
- # compared to the next resolution.
344
- #param_obj.SetParameter("ImagePyramidSchedule", "8 8 4 4 2 2 1 1")
345
- # *********************
346
- # * Sampler parameters
347
- # *********************
348
- # Number of spatial samples used to compute the mutual
349
- # information (and its derivative) in each iteration.
350
- # With an AdaptiveStochasticGradientDescent optimizer,
351
- # in combination with the two options below, around 2000
352
- # samples may already suffice.
353
- param_obj.SetParameter("NumberOfSpatialSamples", "2048")
354
- # Refresh these spatial samples in every iteration, and select
355
- # them randomly. See the manual for information on other sampling
356
- # strategies.
357
- param_obj.SetParameter("NewSamplesEveryIteration", "true")
358
- param_obj.SetParameter("CheckNumberOfSamples", "true")
359
- # *********************
360
- # * Mask settings
361
- # *********************
362
- # If you use a mask, this option is important.
363
- # If the mask serves as region of interest, set it to false.
364
- # If the mask indicates which pixels are valid, then set it to true.
365
- # If you do not use a mask, the option doesn't matter.
366
- param_obj.SetParameter("ErodeMask", "false")
367
- param_obj.SetParameter("ErodeFixedMask", "false")
368
- # *********************
369
- # * Output settings
370
- # *********************
371
- #Default pixel value for pixels that come from outside the picture:
372
- param_obj.SetParameter("DefaultPixelValue", "0")
373
- # Choose whether to generate the deformed moving image.
374
- # You can save some time by setting this to false, if you are
375
- # not interested in the final deformed moving image, but only
376
- # want to analyze the deformation field for example.
377
- param_obj.SetParameter("WriteResultImage", "true")
378
- # The pixel type and format of the resulting deformed moving image
379
- param_obj.SetParameter("ResultImagePixelType", "float")
380
- param_obj.SetParameter("ResultImageFormat", "nii")
381
-
382
- return param_obj
383
-
384
-
385
- def _default_affine(d):
386
- param_obj = itk.ParameterObject.New()
387
- parameter_map_bspline = param_obj.GetDefaultParameterMap('affine')
388
- param_obj.AddParameterMap(parameter_map_bspline)
389
-
390
- # ImageTypes
391
- param_obj.SetParameter("FixedInternalImagePixelType", "float")
392
- param_obj.SetParameter("MovingInternalImagePixelType", "float")
393
- param_obj.SetParameter("FixedImageDimension", d)
394
- param_obj.SetParameter("MovingImageDimension", d)
395
- param_obj.SetParameter("UseDirectionCosines", "true")
396
-
397
- # Components
398
- param_obj.SetParameter("Registration", "MultiResolutionRegistration")
399
- param_obj.SetParameter("ImageSampler", "Random")
400
- param_obj.SetParameter("Interpolator", "BSplineInterpolator")
401
- param_obj.SetParameter("ResampleInterpolator", "FinalBSplineInterpolator")
402
- param_obj.SetParameter("Resampler", "DefaultResampler")
403
- param_obj.SetParameter("BSplineInterpolationOrder", "3")
404
- param_obj.SetParameter("FinalBSplineInterpolationOrder", "3")
405
- param_obj.SetParameter("FixedImagePyramid", "FixedRecursiveImagePyramid")
406
- param_obj.SetParameter("MovingImagePyramid", "MovingRecursiveImagePyramid")
407
-
408
- # Metric
409
- param_obj.SetParameter("Metric", "AdvancedMattesMutualInformation")
410
- param_obj.SetParameter("NumberOfHistogramBins", "32")
411
-
412
- # Transformation
413
- param_obj.SetParameter("Transform", "AffineTransform")
414
- param_obj.SetParameter("HowToCombineTransforms", "Compose")
415
- param_obj.SetParameter("AutomaticTransformInitialization", "false")
416
- param_obj.SetParameter("FinalGridSpacingInPhysicalUnits", "25.0")
417
-
418
- # Optimizer
419
- param_obj.SetParameter("Optimizer", "AdaptiveStochasticGradientDescent")
420
- param_obj.SetParameter("NumberOfResolutions", "4")
421
- param_obj.SetParameter("AutomaticParameterEstimation", "true")
422
- param_obj.SetParameter("ASGDParameterEstimationMethod", "Original")
423
- param_obj.SetParameter("MaximumNumberOfIterations", "500")
424
- param_obj.SetParameter("MaximumStepLength", "1.0")
425
-
426
- # Pyramid settings
427
- param_obj.SetParameter("NumberOfSpatialSamples", "2048")
428
- param_obj.SetParameter("NewSamplesEveryIteration", "true")
429
- param_obj.SetParameter("CheckNumberOfSamples", "true")
430
-
431
- # Mask settings
432
- param_obj.SetParameter("ErodeMask", "false")
433
- param_obj.SetParameter("ErodeFixedMask", "false")
434
-
435
- # Output settings
436
- param_obj.SetParameter("DefaultPixelValue", "0")
437
- param_obj.SetParameter("WriteResultImage", "true")
438
- param_obj.SetParameter("ResultImagePixelType", "float")
439
- param_obj.SetParameter("ResultImageFormat", "nii")
440
-
441
- return param_obj
442
-
443
-
444
- def _default_rigid(d):
445
- param_obj = itk.ParameterObject.New()
446
- parameter_map_bspline = param_obj.GetDefaultParameterMap('rigid')
447
- param_obj.AddParameterMap(parameter_map_bspline)
448
-
449
- # ImageTypes
450
- param_obj.SetParameter("FixedInternalImagePixelType", "float")
451
- param_obj.SetParameter("MovingInternalImagePixelType", "float")
452
- param_obj.SetParameter("FixedImageDimension", d)
453
- param_obj.SetParameter("MovingImageDimension", d)
454
- param_obj.SetParameter("UseDirectionCosines", "true")
455
-
456
- # Components
457
- param_obj.SetParameter("Registration", "MultiResolutionRegistration")
458
- param_obj.SetParameter("ImageSampler", "Random")
459
- param_obj.SetParameter("Interpolator", "BSplineInterpolator")
460
- param_obj.SetParameter("ResampleInterpolator", "FinalBSplineInterpolator")
461
- param_obj.SetParameter("Resampler", "DefaultResampler")
462
- param_obj.SetParameter("BSplineInterpolationOrder", "1")
463
- param_obj.SetParameter("FinalBSplineInterpolationOrder", "3")
464
- param_obj.SetParameter("FixedImagePyramid", "FixedRecursiveImagePyramid")
465
- param_obj.SetParameter("MovingImagePyramid", "MovingRecursiveImagePyramid")
466
- param_obj.SetParameter("Optimizer", "AdaptiveStochasticGradientDescent")
467
-
468
- # Transformation
469
- param_obj.SetParameter("HowToCombineTransforms", "Compose")
470
- param_obj.SetParameter("Transform", "EulerTransform")
471
- param_obj.SetParameter("AutomaticTransformInitialization", "true")
472
- param_obj.SetParameter("AutomaticTransformInitializationMethod", "GeometricalCenter")
473
- param_obj.SetParameter("AutomaticScalesEstimation", "true")
474
-
475
- # Metric
476
- param_obj.SetParameter("Metric", "AdvancedMattesMutualInformation")
477
- param_obj.SetParameter("NumberOfHistogramBins", "32")
478
-
479
- # Optimizer settings
480
- param_obj.SetParameter("NumberOfResolutions", "3")
481
- param_obj.SetParameter("AutomaticParameterEstimation", "true")
482
- #param_obj.SetParameter("ASGDParameterEstimationMethod", "Original")
483
- param_obj.SetParameter("MaximumNumberOfIterations", "500")
484
- param_obj.SetParameter("MaximumStepLength", "1.0")
485
-
486
- # Sampler parameters
487
- param_obj.SetParameter("NumberOfSpatialSamples", "2048")
488
- param_obj.SetParameter("NewSamplesEveryIteration", "true")
489
- param_obj.SetParameter("NumberOfSamplesForExactGradient", "1024")
490
- param_obj.SetParameter("MaximumNumberOfSamplingAttempts", "15")
491
- param_obj.SetParameter("CheckNumberOfSamples", "true")
492
-
493
- # Mask settings
494
- param_obj.SetParameter("ErodeMask", "false")
495
- param_obj.SetParameter("ErodeFixedMask", "false")
496
-
497
- # Output settings
498
- param_obj.SetParameter("DefaultPixelValue", "0")
499
- param_obj.SetParameter("WriteResultImage", "true")
500
- param_obj.SetParameter("ResultImagePixelType", "float")
501
- param_obj.SetParameter("ResultImageFormat", "nii")
502
-
503
- return param_obj
@@ -1,107 +0,0 @@
1
- import numpy as np
2
- import matplotlib.pyplot as plt
3
- from matplotlib.figure import Figure
4
- from mpl_toolkits.mplot3d.art3d import Poly3DCollection
5
- from mpl_toolkits.mplot3d.axes3d import Axes3D
6
- from skimage import measure
7
-
8
- from dbdicom.utils.image import as_mosaic
9
-
10
-
11
- def plot_mosaic(series, zdim='InstanceNumber', rows:int=None, colorbar=True, clim:tuple=None, gridspacing=100, size=10):
12
- """Show a 3D array as a mosaic
13
-
14
- Args:
15
- zdim (str, optional): slice dimension. Defaults to 'InstanceNumber'
16
- series (dbdicom.Series): Series with the array to be plotted.
17
- rows (int, optional): Number of rows of the mosaic. If set to None the mosaic will be chosen to be approximately square. Defaults to None.
18
- colorbar (bool, optional): If True, a color bar is shown next to the mosaic. Defaults to True.
19
- clim (tuple of 2 elements, optional): if provided, this determines the minimal and maximal signal values shown. If it is set to None or not provided, it will be taken from the WindowCenter and WindowWidth values in the DICOM header. Defaults to None.
20
- gridspacing (int, optional): spacing in mm between gridlines on the plot. Defaults to 100 mm.
21
- size (float, optional): size of the largest dimension of the image in inches. Defaults to 10 inch
22
- """
23
- array = series.pixel_values(dims=(zdim,))
24
- spacing = series.spacing()
25
- mosaic = as_mosaic(array, rows=rows)
26
- cols = mosaic.shape[1]/spacing[1]
27
-
28
- if clim is None:
29
- c, w = series.WindowCenter, series.WindowWidth
30
- clim = (c-w/2, c+w/2)
31
- fig, ax = plt.subplots()
32
- dx, dy = spacing[0]*mosaic.shape[0], spacing[1]*mosaic.shape[1]
33
- size = 10
34
- fig.set_size_inches(size*dx/np.amax([dx,dy]), size*dy/np.amax([dx,dy]))
35
- im = ax.imshow(mosaic.T, clim=clim)
36
- ax.set_xlabel("x-axis (mm)")
37
- ax.set_ylabel("y-axis (mm)")
38
- x = np.arange(0, 1+mosaic.shape[0], gridspacing/spacing[0])
39
- y = np.arange(0, 1+mosaic.shape[1], gridspacing/spacing[1])
40
- ax.set_xticks(x, np.int16(x*spacing[0]))
41
- ax.set_yticks(y, np.int16(y*spacing[1]))
42
- if colorbar:
43
- fig.colorbar(im, ax=ax, label='Signal')
44
- plt.show()
45
-
46
-
47
- def plot_surface(series, level=0, gridspacing=10, show=True):
48
- """Plot the surface at a given level
49
-
50
- Args:
51
- series (dbdicom.Series): Series with the array to be plotted.
52
- level (int, optional): Extract the surface at this level. Defaults to 0.
53
- gridspacing (int, optional): spacing in mm between gridlines on the plot. Defaults to 10 mm.
54
- show (bool, optional): if True, the function displays the plot. Defaults to True.
55
-
56
- Returns:
57
- Figure: matplotlib figure with the plot.
58
-
59
- Requires:
60
- matplotlib
61
- skimage
62
- """
63
-
64
- # Extract the numpy array from the dbdicom series:
65
- array = series.pixel_values()
66
- spacing = series.spacing()
67
- #spacing = (spacing[1], spacing[0], spacing[2])
68
-
69
- # Use marching cubes to extract the surface from the array
70
- verts, faces, _, _ = measure.marching_cubes(array, level)
71
-
72
- # Use the matplotlib toolkit to create a trinagular mesh
73
- mesh = Poly3DCollection(verts[faces])
74
- mesh.set_edgecolor('k')
75
-
76
- fig = plt.figure(figsize=(10, 10))
77
- ax = fig.add_subplot(111, projection='3d')
78
- ax.add_collection3d(mesh)
79
-
80
- ax.set_xlabel("x-axis (mm)")
81
- ax.set_ylabel("y-axis (mm)")
82
- ax.set_zlabel("z-axis (mm)")
83
-
84
- x = np.arange(0, 1+array.shape[0], gridspacing/spacing[0])
85
- y = np.arange(0, 1+array.shape[1], gridspacing/spacing[1])
86
- z = np.arange(0, 1+array.shape[2], gridspacing/spacing[2])
87
-
88
- ax.set_xticks(x, np.int16(x*spacing[0]))
89
- ax.set_yticks(y, np.int16(y*spacing[1]))
90
- ax.set_zticks(z, np.int16(z*spacing[2]))
91
-
92
- # Hack to ensure proportional size of each axis
93
- x_len = array.shape[0]*spacing[0]
94
- y_len = array.shape[1]*spacing[1]
95
- z_len = array.shape[2]*spacing[2]
96
-
97
- scale=np.diag([x_len, y_len, z_len, 1.0])
98
- scale=scale*(1.0/scale.max())
99
- scale[3,3]=1.0
100
-
101
- def short_proj():
102
- return np.dot(Axes3D.get_proj(ax), scale)
103
-
104
- ax.get_proj = short_proj
105
-
106
- if show:
107
- plt.show()