示例#1
0
    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))
示例#2
0
    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()
示例#4
0
        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)))
示例#5
0
    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)
示例#6
0
 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
示例#7
0
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