From bbb98660003f65a31dd464f11286ddf842311b2f Mon Sep 17 00:00:00 2001 From: Charles Bouman <Charles.Bouman@gmail.com> Date: Sat, 4 Jun 2022 18:34:03 -0400 Subject: [PATCH 1/4] Changed default iterations to 100 --- demo/demo_3D_shepp_logan.py | 41 ++++++++++++++++++++++--------------- mbircone/cone3D.py | 4 ++-- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/demo/demo_3D_shepp_logan.py b/demo/demo_3D_shepp_logan.py index 61779ec..c5be708 100644 --- a/demo/demo_3D_shepp_logan.py +++ b/demo/demo_3D_shepp_logan.py @@ -31,9 +31,15 @@ num_views = 64 # projection angles will be uniformly spaced within the range [0, 2*pi). angles = np.linspace(0, 2 * np.pi, num_views, endpoint=False) # qGGMRF recon parameters -sharpness = 2.0 # Controls regularization level of reconstruction -max_iterations=40 -stop_threshold=0.005 +sharpness = 1.0 # Controls regularization level of reconstruction by controling prior term weighting +snr_db = 40 # Controls regularization level of reconstruction by controling data term weighting +T = 0.1 # Controls edginess of reconstruction +# convergence parameters +stop_threshold = 0.005 +# display parameters +vmin = 0.10 +vmax = 0.12 + # local path to save phantom, sinogram, and reconstruction images save_path = f'output/3D_shepp_logan/' os.makedirs(save_path, exist_ok=True) @@ -57,8 +63,10 @@ print('ROI shape is:', num_slices_ROI, num_rows_ROI, num_cols_ROI) ###################################################################################### # Generate a 3D shepp logan phantom with size calculated in previous section ###################################################################################### -phantom = mbircone.phantom.gen_shepp_logan_3d(num_rows_ROI, num_cols_ROI, num_slices_ROI) # generate phantom within ROI +phantom = mbircone.phantom.gen_shepp_logan_3d(num_rows_ROI, num_cols_ROI, num_slices_ROI) # generate phantom within ROI phantom = mbircone.cone3D.pad_roi2ror(phantom, boundary_size) # zero-pad phantom to ROR +# scale the phantom by a factor of 10.0 to make the projections physical realistic -log attenuation values +phantom = phantom/10.0 print('Padded ROR phantom shape = ', np.shape(phantom)) @@ -76,17 +84,14 @@ print('Synthetic sinogram shape: (num_views, num_det_rows, num_det_channels) = ' # Perform 3D qGGMRF reconstruction ###################################################################################### print('Performing 3D qGGMRF reconstruction ...') -recon = mbircone.cone3D.recon(sino, angles, - dist_source_detector, magnification, - sharpness=sharpness, - max_iterations=max_iterations, stop_threshold=stop_threshold) +recon = mbircone.cone3D.recon(sino, angles, dist_source_detector, magnification, sharpness=sharpness, snr_db = snr_db, T = T, stop_threshold = stop_threshold) print('recon shape = ', np.shape(recon)) ###################################################################################### # Generate phantom, synthetic sinogram, and reconstruction images ###################################################################################### -# Generate sino and recon images +# sinogram images for view_idx in [0, num_views//4, num_views//2]: view_angle = int(angles[view_idx]*180/np.pi) plot_image(sino[view_idx, :, :], title=f'sinogram view angle {view_angle} ', @@ -97,17 +102,21 @@ display_x = num_rows_ROR // 2 display_y = num_cols_ROR // 2 # phantom images plot_image(phantom[display_slice], title=f'phantom, axial slice {display_slice}', - filename=os.path.join(save_path, 'phantom_axial.png'), vmin=1.0, vmax=1.1) -plot_image(phantom[:,display_x,:], title=f'phantom, coronal slice {display_x}', - filename=os.path.join(save_path, 'phantom_coronal.png'), vmin=1.0, vmax=1.1) + filename=os.path.join(save_path, 'phantom_axial.png'), vmin=0, vmax=0.40) +plot_image(phantom[display_slice], title=f'phantom, axial slice {display_slice}', + filename=os.path.join(save_path, 'phantom_axial.png'), vmin=vmin, vmax=vmax) +plot_image(phantom[:,display_x,:], title=f'phantom, coronal slice {display_x}', + filename=os.path.join(save_path, 'phantom_coronal.png'), vmin=vmin, vmax=vmax) plot_image(phantom[:,:,display_y], title=f'phantom, sagittal slice {display_y}', - filename=os.path.join(save_path, 'phantom_sagittal.png'), vmin=1.0, vmax=1.1) + filename=os.path.join(save_path, 'phantom_sagittal.png'), vmin=vmin, vmax=vmax) # recon images plot_image(recon[display_slice], title=f'qGGMRF recon, axial slice {display_slice}', - filename=os.path.join(save_path, 'recon_axial.png'), vmin=1.0, vmax=1.1) + filename=os.path.join(save_path, 'recon_axial.png'), vmin=0, vmax=0.40) +plot_image(recon[display_slice], title=f'qGGMRF recon, axial slice {display_slice}', + filename=os.path.join(save_path, 'recon_axial.png'), vmin=vmin, vmax=vmax) plot_image(recon[:,display_x,:], title=f'qGGMRF recon, coronal slice {display_x}', - filename=os.path.join(save_path, 'recon_coronal.png'), vmin=1.0, vmax=1.1) + filename=os.path.join(save_path, 'recon_coronal.png'), vmin=vmin, vmax=vmax) plot_image(recon[:,:,display_y], title=f'qGGMRF recon, sagittal slice {display_y}', - filename=os.path.join(save_path, 'recon_sagittal.png'), vmin=1.0, vmax=1.1) + filename=os.path.join(save_path, 'recon_sagittal.png'), vmin=vmin, vmax=vmax) print(f"Images saved to {save_path}.") input("Press Enter") diff --git a/mbircone/cone3D.py b/mbircone/cone3D.py index 4d182f7..e05e1b1 100644 --- a/mbircone/cone3D.py +++ b/mbircone/cone3D.py @@ -486,7 +486,7 @@ def recon(sino, angles, dist_source_detector, magnification, init_image=0.0, prox_image=None, sigma_y=None, snr_db=30.0, weights=None, weight_type='unweighted', positivity=True, p=1.2, q=2.0, T=1.0, num_neighbors=6, - sharpness=0.0, sigma_x=None, sigma_p=None, max_iterations=20, stop_threshold=0.02, + sharpness=0.0, sigma_x=None, sigma_p=None, max_iterations=100, stop_threshold=0.02, num_threads=None, NHICD=False, verbose=1, lib_path=__lib_path): """Compute 3D cone beam MBIR reconstruction @@ -541,7 +541,7 @@ def recon(sino, angles, dist_source_detector, magnification, sigma_p (float, optional): [Default=None] Scalar value :math:`>0` that specifies the proximal map parameter. Ignored if prox_image is None. If None and proximal image is not None, automatically set with auto_sigma_p. Regularization should be controled with the ``sharpness`` parameter, but ``sigma_p`` can be set directly by expert users. - max_iterations (int, optional): [Default=20] Integer valued specifying the maximum number of iterations. + max_iterations (int, optional): [Default=100] Integer valued specifying the maximum number of iterations. stop_threshold (float, optional): [Default=0.02] Scalar valued stopping threshold in percent. If stop_threshold=0.0, then run max iterations. num_threads (int, optional): [Default=None] Number of compute threads requested when executed. -- GitLab From ef15bb41490a0005c0a45fec36545f9c4d8c1f3e Mon Sep 17 00:00:00 2001 From: dyang37 <yang1467@purdue.edu> Date: Sun, 5 Jun 2022 14:48:55 -0400 Subject: [PATCH 2/4] change default snr_db value from 30.0 to 40.0 --- mbircone/cone3D.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mbircone/cone3D.py b/mbircone/cone3D.py index e05e1b1..1e09e12 100644 --- a/mbircone/cone3D.py +++ b/mbircone/cone3D.py @@ -122,7 +122,7 @@ def calc_weights(sino, weight_type): return weights -def auto_sigma_y(sino, magnification, weights, snr_db=30.0, delta_pixel_image=1.0, delta_pixel_detector=1.0): +def auto_sigma_y(sino, magnification, weights, snr_db=40.0, delta_pixel_image=1.0, delta_pixel_detector=1.0): """Compute the automatic value of ``sigma_y`` for use in MBIR reconstruction. Args: @@ -132,7 +132,7 @@ def auto_sigma_y(sino, magnification, weights, snr_db=30.0, delta_pixel_image=1. numpy array of weights with same shape as sino. The parameters weights should be the same values as used in mbircone reconstruction. snr_db (float, optional): - [Default=30.0] Scalar value that controls assumed signal-to-noise ratio of the data in dB. + [Default=40.0] Scalar value that controls assumed signal-to-noise ratio of the data in dB. delta_pixel_image (float, optional): [Default=1.0] Scalar value of pixel spacing in :math:`ALU`. delta_pixel_detector (float, optional): @@ -484,7 +484,7 @@ def recon(sino, angles, dist_source_detector, magnification, channel_offset=0.0, row_offset=0.0, rotation_offset=0.0, delta_pixel_detector=1.0, delta_pixel_image=None, ror_radius=None, init_image=0.0, prox_image=None, - sigma_y=None, snr_db=30.0, weights=None, weight_type='unweighted', + sigma_y=None, snr_db=40.0, weights=None, weight_type='unweighted', positivity=True, p=1.2, q=2.0, T=1.0, num_neighbors=6, sharpness=0.0, sigma_x=None, sigma_p=None, max_iterations=100, stop_threshold=0.02, num_threads=None, NHICD=False, verbose=1, lib_path=__lib_path): @@ -513,7 +513,7 @@ def recon(sino, angles, dist_source_detector, magnification, sigma_y (float, optional): [Default=None] Scalar value of noise standard deviation parameter. If None, automatically set with auto_sigma_y. - snr_db (float, optional): [Default=30.0] Scalar value that controls assumed signal-to-noise ratio of the data in dB. + snr_db (float, optional): [Default=40.0] Scalar value that controls assumed signal-to-noise ratio of the data in dB. Ignored if sigma_y is not None. weights (ndarray, optional): [Default=None] 3D weights array with same shape as sino. weight_type (string, optional): [Default='unweighted'] Type of noise model used for data. -- GitLab From 3c8303c966cd1f087630dc9a0c94dbcada4df69d Mon Sep 17 00:00:00 2001 From: dyang37 <yang1467@purdue.edu> Date: Sun, 5 Jun 2022 14:50:20 -0400 Subject: [PATCH 3/4] remove snr_db variable from 3D shepp logan demo, since now the default value is 40.0. --- demo/demo_3D_shepp_logan.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/demo/demo_3D_shepp_logan.py b/demo/demo_3D_shepp_logan.py index c5be708..d361d4c 100644 --- a/demo/demo_3D_shepp_logan.py +++ b/demo/demo_3D_shepp_logan.py @@ -32,7 +32,6 @@ num_views = 64 angles = np.linspace(0, 2 * np.pi, num_views, endpoint=False) # qGGMRF recon parameters sharpness = 1.0 # Controls regularization level of reconstruction by controling prior term weighting -snr_db = 40 # Controls regularization level of reconstruction by controling data term weighting T = 0.1 # Controls edginess of reconstruction # convergence parameters stop_threshold = 0.005 @@ -84,7 +83,7 @@ print('Synthetic sinogram shape: (num_views, num_det_rows, num_det_channels) = ' # Perform 3D qGGMRF reconstruction ###################################################################################### print('Performing 3D qGGMRF reconstruction ...') -recon = mbircone.cone3D.recon(sino, angles, dist_source_detector, magnification, sharpness=sharpness, snr_db = snr_db, T = T, stop_threshold = stop_threshold) +recon = mbircone.cone3D.recon(sino, angles, dist_source_detector, magnification, sharpness=sharpness, T = T, stop_threshold = stop_threshold) print('recon shape = ', np.shape(recon)) -- GitLab From 57f181641b49d87ec9204d81e15057438293e8dc Mon Sep 17 00:00:00 2001 From: Charles Bouman <Charles.Bouman@gmail.com> Date: Sun, 5 Jun 2022 16:29:40 -0400 Subject: [PATCH 4/4] Reduce default blocksize parameter for shepp-logan phantom --- mbircone/phantom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mbircone/phantom.py b/mbircone/phantom.py index 4213247..757b97d 100644 --- a/mbircone/phantom.py +++ b/mbircone/phantom.py @@ -77,7 +77,7 @@ def gen_microscopy_sample(num_rows, num_cols): return image -def gen_shepp_logan_3d(num_rows, num_cols, num_slices, block_size=(4,4,4)): +def gen_shepp_logan_3d(num_rows, num_cols, num_slices, block_size=(2,2,2)): """ Generate a smoothed 3D Shepp Logan phantom with block-averaging strategy. -- GitLab