def test_combine_images(self): # Load in a shepp logan phantom, 2D dim = 32 im = np.rot90( modified_shepp_logan((dim, dim, dim))[:, :, int(dim / 2)]) im_size = (10, 10) # cm x cm # Compute in-plane voxel size in millimeters voxel_size = [10 * im_size[ii] / dim for ii in range(len(im_size))] # print(voxel_size) # Now we want to split this image into 2 parts, both with the same # resolution, but one offset from the other by half a pixel in one # dimension, say along the x-axis im0 = np.zeros((dim, int(dim / 2) - 1)) im1 = np.zeros((dim, int(dim / 2) - 1)) for jj in range(im0.shape[1] - 1): for ii in range(im0.shape[0]): im0[ii, jj] = np.sum(im[ii, 2 * jj:2 * jj + 2]) im1[ii, jj] = np.sum(im[ii, 2 * jj + 1:2 * jj + 2 + 1]) # plt.subplot(1,3,1) # plt.imshow(im0) # plt.subplot(1,3,2) # plt.imshow(im1) # plt.subplot(1,3,3) # plt.imshow(im0 - im1) # plt.show() im_hat = combine_images(im0, im1) self.assertTrue(np.allclose(im[:, 1:-1], im_hat))
def test_motion(self): from mr_utils.sim.motion import cartesian_acquire from mr_utils.test_data.phantom import modified_shepp_logan # Load in a shepp logan phantom, 2D dim = 64 im = modified_shepp_logan((dim, dim, dim))[:, :, int(dim / 2)] im_dims = (.05, .05) # cm x cm image # Create a position function for the object in image space # pos = (lambda t: 0,lambda t: 0) # pos = (lambda t: .0035*t,lambda t: 0) pos = (lambda t: .0025 * np.sin(t * 5), lambda t: 0) # The time grid defines the kspace trajectory and the times each voxel # gets measured row_time = 2e-3 # seconds for one phase encode TR = 5e-3 # TR must be greater than the time it takes to get one row self.assertLess(row_time, TR) t0 = 0 # time at the beginning of a row pts_per_line = dim PEs = dim time_grid = np.zeros((PEs, pts_per_line)) for row in range(PEs): # Row starts at t0 and ends after the time it takes to get a row time_grid[row, :] = np.linspace(t0, t0 + row_time, pts_per_line) # The new start time happens after TR t0 += TR cartesian_acquire(im, im_dims, pos, time_grid)
def test_partial_fourier_pocs(self): from mr_utils.recon.partial_fourier import partial_fourier_pocs from mr_utils.test_data.phantom import modified_shepp_logan # Get something to test on dim = 64 im = modified_shepp_logan((dim, dim, dim))[:, :, int(dim / 2)] kspace_all = np.fft.fftshift(np.fft.fft2(im)) kspace = np.zeros(kspace_all.shape, dtype='complex') # Now simulate the partial fourier pf_factor = 7 / 8 startRO, endRO = int((1 - pf_factor) * dim), dim - 1 startE1, endE1 = 0, dim - 1 kspace[startRO:endRO:, startE1:endE1:] = kspace_all[startRO:endRO:, startE1:endE1:] # Run the POCS recon res_kspace = partial_fourier_pocs(kspace, startRO, endRO, startE1, endE1, niter=1000, thres=1e-8) plt.subplot(1, 3, 1) plt.imshow(np.abs(np.fft.fft2(kspace_all)), cmap='gray') plt.title('Fully sampled') plt.subplot(1, 3, 2) plt.imshow(np.abs(np.fft.fft2(kspace)), cmap='gray') plt.title('Zero-pad recon') plt.subplot(1, 3, 3) plt.imshow(np.abs(np.fft.ifft2(res_kspace)), cmap='gray') plt.title('Partial Fourier POCS recon') plt.show()
a = 2 * ((H1 - H2)**2).astype(float) b = H1 + H2 return np.sum(np.divide(a, b, out=np.zeros_like(a), where=b != 0)) if mode == 'jsd': return jensenshannon(H1, H2) if mode == 'emd': return wasserstein_distance(H1, H2) raise NotImplementedError() if __name__ == '__main__': # Make a phantom to work with, shepp_logan will do dim = 32 x = np.rot90(modified_shepp_logan((dim, ) * 3)[:, :, int(dim / 2)]) # view(x) # Define transform level = 3 wavelets = ['haar', 'db', 'sym', 'coif', 'bior', 'rbio', 'dmey'] modes = [ 'zero', 'constant', 'symmetric', 'reflect', 'periodic', 'smooth', 'periodization' ] wavelet = wavelets[1] + '2' mode = modes[-1] wvlt, loc = wavelet_forward(x, wavelet, mode, level) T = lambda x: wavelet_forward(x, wavelet, mode, level)[0] Ti = lambda x: wavelet_inverse(x, loc, wavelet, mode) assert np.allclose(x, Ti(T(x)))
def test_reorder(self): from mr_utils.test_data.phantom import modified_shepp_logan from mr_utils.recon.reordering import get_patches # Get phantom dim = 64 phantom = np.rot90( modified_shepp_logan((dim, dim, dim))[:, :, int(dim / 2)]) kspace = np.fft.fftshift(np.fft.fft2(phantom)) imspace = np.fft.ifft2(kspace) # Get patches patches = get_patches(imspace, (3, 3)) # Take mean of each patch to be the pixel value im = np.mean(patches, axis=(-2, -1)) # view(im) # # Try 2d reordering and using Ganesh's MATLAB script to do recon # # view(im) # im_sorted,idx = sort2d(im) # default sort by real # self.assertTrue(np.allclose(im.take(idx),im_sorted)) # # Run Ganesh's recon # client = Client() # client.run('cd mr_utils/recon/reordering/spatial_tv') # client.run('run SCR_reordering.m') # data = client.get([ 'Coil1','img_est','measuredImgDomain','prior_data' ]) # client.exit() # # Run Ganesh's temporal recon # client = Client() # client.run('cd mr_utils/recon/reordering/temporal_tv') # client.run('run TCR_reordering_main.m') # data = client.get([ 'Coil','mask_k_space_sparse','recon_data' ]) # client.exit() # np.save('mr_utils/recon/reordering/temporal_tv/data.npy',data) data = np.load('mr_utils/recon/reordering/temporal_tv/data.npy').item() # Get reference, recon, and prior image estimates coil_imspace = np.fft.fftshift(np.fft.fft2(data['Coil'], axes=(0, 1)), axes=(0, 1)) recon_flipped = np.rot90(np.rot90(data['recon_data'])).astype( coil_imspace.dtype) prior = np.fft.fftshift(np.fft.fft2(data['Coil'] * data['mask_k_space_sparse'], axes=(0, 1)), axes=(0, 1)) # Normalize so they are comparable abs_coil_imspace = np.abs(coil_imspace) abs_coil_imspace /= np.max(abs_coil_imspace) abs_recon_flipped = np.abs(recon_flipped) abs_recon_flipped /= np.max(abs_recon_flipped) abs_prior = np.abs(prior) abs_prior /= np.max(abs_prior) r_coil_imspace = coil_imspace.real / np.max(np.abs(coil_imspace.real)) i_coil_imspace = coil_imspace.imag / np.max(np.abs(coil_imspace.imag)) r_recon_flipped = recon_flipped.real / np.max( np.abs(recon_flipped.real)) i_recon_flipped = recon_flipped.imag / np.max( np.abs(recon_flipped.imag)) r_prior = prior.real / np.max(np.abs(prior.real)) i_prior = prior.imag / np.max(np.abs(prior.imag)) # Comparisons print('MSE of px reorder: %g' % (.5 * (compare_mse(r_coil_imspace, r_recon_flipped) + compare_mse(i_coil_imspace, i_recon_flipped)))) print('SSIM of px reorder: %g' % compare_ssim(abs_coil_imspace, abs_recon_flipped)) print('PSNR of px reorder: %g' % compare_psnr(abs_coil_imspace, abs_recon_flipped)) print( 'MSE of patch reorder: %g' % (.5 * (compare_mse(r_coil_imspace, ) + compare_mse(i_coil_imspace, )))) print('SSIM of patch reorder: %g' % compare_ssim(abs_coil_imspace, )) print('PSNR of patch reorder: %g' % compare_psnr(abs_coil_imspace, )) # # These are different because of scaling: # # print('MSE of prior: %g' % compare_mse(abs_coil_imspace,abs_prior)) # print('MSE of prior: %g' % ((compare_mse(r_coil_imspace,r_prior) + compare_mse(i_coil_imspace,i_prior))/2)) # print('SSIM of prior: %g' % compare_ssim(abs_coil_imspace,abs_prior)) # print('PSNR of prior: %g' % compare_psnr(abs_coil_imspace,abs_prior)) view(prior) view(recon_flipped)
def test_single_voxel(self): # Load in a shepp logan phantom, 2D dim = 32 im = np.rot90( modified_shepp_logan((dim, dim, dim))[:, :, int(dim / 2)]) patch_size = (8, 4) # pixel by pixel
from mr_utils.cs import proximal_GD from mr_utils.cs import relaxed_ordinator from mr_utils.utils.wavelet import cdf97_2d_forward, cdf97_2d_inverse from mr_utils.utils.sort2d import sort2d from mr_utils import view from mr_utils.definitions import ROOT_DIR if __name__ == '__main__': # Sim params N = 64 # x is NxN num_spokes = 16 run = ['monosort', 'lagrangian'] # none is always run to get prior # Need a reasonable numerical phantom x = np.rot90(modified_shepp_logan((N, N, N))[:, :, int(N / 2)]) # view(x) # Sparsifying transform level = 3 wvlt, locations = cdf97_2d_forward(x, level) sparsify = lambda x: cdf97_2d_forward(x, level)[0] unsparsify = lambda x: cdf97_2d_inverse(x, locations) # Do radial golden-angle sampling mask = radial(x.shape, num_spokes, skinny=True, extend=False) uft = UFT(mask) kspace_u = uft.forward_ortho(x) view(kspace_u, fft=True) # # We need to find the best alpha for the no ordering recon