Example #1
0
    def test_shepp_logan(self):
        '''The much-abused Shepp-Logan.'''

        ph = shepp_logan(self.N)
        ph /= np.max(ph.flatten())
        phs = ph[..., None] * self.mps

        kspace = np.fft.ifftshift(np.fft.fft2(np.fft.fftshift(phs,
                                                              axes=(0, 1)),
                                              axes=(0, 1)),
                                  axes=(0, 1))
        kspace_u = np.array(np.zeros_like(kspace))  # wrap for pylint
        kspace_u[:, ::2, :] = kspace[:, ::2, :]
        ctr = int(self.N / 2)
        pd = 5
        calib = kspace[:, ctr - pd:ctr + pd, :].copy()

        recon = grappa(kspace_u, calib, (5, 5), coil_axis=-1)
        recon = np.fft.fftshift(np.fft.ifft2(np.fft.ifftshift(recon,
                                                              axes=(0, 1)),
                                             axes=(0, 1)),
                                axes=(0, 1))
        recon = np.abs(np.sqrt(np.sum(recon * np.conj(recon), axis=-1)))
        recon /= np.max(recon.flatten())

        # Make sure less than 4% NRMSE
        # print(compare_nrmse(ph, recon))
        self.assertTrue(compare_nrmse(ph, recon) < .04)
Example #2
0
    def test_shepplogan_init_returns_expected_starting_volume(self):
        test_obj = NumericalModel(model="shepp-logan")

        expected_volume = shepp_logan(128)
        actual_volume = test_obj._starting_volume

        np.testing.assert_array_equal(actual_volume, expected_volume)
Example #3
0
    def test_shepplogan_dims_init_returns_expected_starting_volume(self):
        dims = 256
        test_obj = NumericalModel(model="shepp-logan", num_vox=dims)

        expected_volume = shepp_logan(dims)
        actual_volume = test_obj._starting_volume

        np.testing.assert_array_equal(actual_volume, expected_volume)
Example #4
0
def shepp_logan2d(M=64, N=64, nc=4, dtype=np.complex128):
    '''Make 2d phantom.'''
    ax = (0, 1)
    imspace = shepp_logan((M, N))
    mps = gaussian_csm(M, N, nc)
    coil_ims = imspace[..., None]*mps
    coil_ims = coil_ims.astype(dtype)
    kspace = np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(
        coil_ims, axes=ax), axes=ax, norm='ortho'), axes=ax)
    kspace = kspace.astype(dtype)
    imspace = np.abs(imspace)
    imspace /= np.max(imspace.flatten())  # normalize
    return(imspace, coil_ims, kspace, mps)
Example #5
0
    def _shepp_logan_brain(self, numVox):
        self._starting_volume = shepp_logan(numVox)

        self._volume["proton_density"] = self._customize_shepp_logan(
            self._starting_volume,
            self.proton_density["WM"],
            self.proton_density["GM"],
            self.proton_density["CSF"],
        )
        self._volume["T2_star"] = self._customize_shepp_logan(
            self._starting_volume,
            self.T2_star["WM"],
            self.T2_star["GM"],
            self.T2_star["CSF"],
        )
Example #6
0
from phantominator import shepp_logan
from matplotlib import pyplot as plt
import numpy as np
import pynufft as pnft

#create the shepp_logan phantom
ph = shepp_logan(16)

for i in range(8):
    ph[:, i] = [1] * 16

for i in range(8, 16):
    ph[:, i] = [0.5] * 16

plt.title('phantom'), plt.xticks([]), plt.yticks([])
plt.imshow(ph, cmap='gray')
plt.show()


#function that draws the k-space under the effect of the non-uniform B0
def non_uniform_kspace(phantom):
    NufftObj = pnft.NUFFT()
    Nd = (phantom.shape[0], phantom.shape[1])
    Kd = (2 * phantom.shape[0], 2 * phantom.shape[1])
    Jd = (6, 6)
    om = np.random.randn(15120, 3)
    NufftObj.plan(om, Nd, Kd, Jd)
    x = NufftObj.forward(phantom)
    Data = NufftObj.solve(x, solver='cg', maxiter=50)
    k = np.fft.fft2(Data)
    k_space = (np.fft.fftshift(k)) / np.sqrt(k)
Example #7
0
'''Show basic usage of NL-GRAPPA MATLAB port.'''

import numpy as np
import matplotlib.pyplot as plt
from phantominator import shepp_logan

from pygrappa import nlgrappa_matlab
from utils import gaussian_csm

if __name__ == '__main__':

    # Generate data
    N, nc = 128, 8
    sens = gaussian_csm(N, N, nc)
    im = shepp_logan(N)
    im = im[..., None]*sens
    sos = np.sqrt(np.sum(np.abs(im)**2, axis=-1))

    off = 0  # starting sampling location

    # The number of ACS lines
    R = 5
    nencode = 42

    # The convolution size
    num_block = 2
    num_column = 15  # make smaller to go quick during development

    # Obtain ACS data and undersampled data
    sx, sy, nc = im.shape[:]
    sx2 = int(sx/2)
Example #8
0
'''Demonstrate how to use MR Shepp-Logan.'''

import matplotlib.pyplot as plt

from phantominator import shepp_logan

if __name__ == '__main__':

    # Get proton density, T1, and T2 maps for (L, M, N) sized Shepp-
    # Logan phantom.
    L, M, N = 256, 255, 20
    M0, T1, T2 = shepp_logan((L, M, N), MR=True, zlims=(-.25, .25))

    # Take a look
    nx, ny = 2, 2
    plt.subplot(nx, ny, 1)
    plt.imshow(M0[..., 0])
    plt.title('Proton Density')
    plt.axis('off')

    plt.subplot(nx, ny, 2)
    plt.imshow(T1[..., 0])
    plt.title('T1')
    plt.axis('off')

    plt.subplot(nx, ny, 3)
    plt.imshow(T2[..., 0])
    plt.title('T2')
    plt.axis('off')

    plt.show()
Example #9
0
pyfftw.interfaces.cache.enable()

#parameters
N = 256
floatType = np.complex
twoQuads = True
p = nt.nearestPrime(N)
p = N

#-------------------------------
#load kspace data
#from scipy.io import loadmat

#load Cartesian data
#Attention: You must ensure the kspace data is correctly centered or not centered.
image = shepp_logan(N)
kspace = fftpack.fft2(image)
print("kSpace Shape:", kspace.shape)
kMaxValue = np.max(kspace)
kMinValue = np.min(kspace)
print("k-Space Max Value:", kMaxValue)
print("k-Space Min Value:", kMinValue)
print("k-Space Max Magnitude:", np.abs(kMaxValue))
print("k-Space Min Magnitude:", np.abs(kMinValue))

#-------------------------------
#compute the Cartesian reconstruction for comparison
print("Computing Chaotic Reconstruction...")
dftSpace = kspace
image = fftpack.ifft2(dftSpace)  #the '2' is important
image = np.abs(image)
Example #10
0
'''Demonstrate usage of iGRAPPA.'''

import numpy as np
import matplotlib.pyplot as plt
from phantominator import shepp_logan

from pygrappa import igrappa, cgrappa
from utils import gaussian_csm

if __name__ == '__main__':

    # Simple phantom
    N = 128
    ncoil = 5
    csm = gaussian_csm(N, N, ncoil)
    ph = shepp_logan(N)[..., None]*csm

    # Throw into k-space
    ax = (0, 1)
    kspace = np.fft.ifftshift(np.fft.fft2(np.fft.fftshift(
        ph, axes=ax), axes=ax), axes=ax)
    ref = kspace.copy()

    # Small ACS region: 4x4
    pad = 2
    ctr = int(N/2)
    calib = kspace[ctr-pad:ctr+pad, ctr-pad:ctr+pad, :].copy()

    # R=2x2
    kspace[::2, 1::2, :] = 0
    kspace[1::2, ::2, :] = 0
Example #11
0
'''Show basic usage of GS solution.'''

import numpy as np
import matplotlib.pyplot as plt
from phantominator import shepp_logan
from ssfp import bssfp, gs_recon

if __name__ == '__main__':

    # Shepp-Logan
    N = 128
    M0 = shepp_logan(N)
    T1, T2 = M0 * 2, M0 / 2

    # Simulate bSSFP acquisition with linear off-resonance
    TR, alpha = 3e-3, np.deg2rad(30)
    pcs = np.linspace(0, 2 * np.pi, 4, endpoint=False)
    df, _ = np.meshgrid(np.linspace(-1 / TR, 1 / TR, N),
                        np.linspace(-1 / TR, 1 / TR, N))
    sig = bssfp(T1,
                T2,
                TR,
                alpha,
                field_map=df,
                phase_cyc=pcs[None, None, :],
                M0=M0)

    # Show the phase-cycled images
    nx, ny = 2, 2
    plt.figure()
    for ii in range(nx * ny):
Example #12
0
'''Basic usage of CG-SENSE implementation.'''

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from phantominator import shepp_logan

from pygrappa import cgsense
from utils import gaussian_csm

if __name__ == '__main__':

    N, nc = 128, 4
    sens = gaussian_csm(N, N, nc)

    im = shepp_logan(N)
    im = im[..., None] * sens
    kspace = np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(im, axes=(0, 1)),
                                         axes=(0, 1)),
                             axes=(0, 1))

    # Undersample
    kspace[::2, 1::2, :] = 0
    kspace[1::2, ::2, :] = 0

    # SOS of the aliased image
    aliased = np.fft.ifftshift(np.fft.ifft2(np.fft.fftshift(kspace,
                                                            axes=(0, 1)),
                                            axes=(0, 1)),
                               axes=(0, 1))
    aliased = np.sqrt(np.sum(np.abs(aliased)**2, axis=-1))
Example #13
0
def planet_shepp_logan_example():

    # Shepp-Logan
    N, nslices, npcs = 128, 1, 8  # 2 slices just to show we can
    M0, T1, T2 = shepp_logan((N, N, nslices), MR=True, zlims=(-.25, 0))

    # Simulate bSSFP acquisition with linear off-resonance
    TR, alpha = 3e-3, np.deg2rad(15)
    pcs = np.linspace(0, 2 * np.pi, npcs, endpoint=False)
    df, _ = np.meshgrid(np.linspace(-1 / TR, 1 / TR, N),
                        np.linspace(-1 / TR, 1 / TR, N))
    sig = np.empty((npcs, ) + T1.shape, dtype='complex')
    for sl in range(nslices):
        sig[..., sl] = bssfp(T1[..., sl],
                             T2[..., sl],
                             TR,
                             alpha,
                             field_map=df,
                             phase_cyc=pcs,
                             M0=M0[..., sl])

    # Do T1, T2 mapping for each pixel
    mask = np.abs(M0) > 1e-8

    # Make it noisy
    np.random.seed(0)
    sig += 1e-5 * (np.random.normal(0, 1, sig.shape) +
                   1j * np.random.normal(0, 1, sig.shape)) * mask

    print(sig.shape, alpha, TR, mask.shape)

    # Show the phase-cycled images
    nx, ny = 2, 4
    plt.figure()
    for ii in range(nx * ny):
        plt.subplot(nx, ny, ii + 1)
        plt.imshow(np.abs(sig[ii, :, :, 0]))
        plt.title('%d deg PC' % (ii * (360 / npcs)))
    plt.show()

    # Do the thing
    t0 = perf_counter()
    Mmap, T1est, T2est, dfest = planet(sig, alpha, TR, mask=mask, pc_axis=0)
    print('Took %g sec to run PLANET' % (perf_counter() - t0))

    print(T1est.shape, T2est.shape, dfest.shape, T1.shape, T2.shape,
          mask.shape)

    # Look at a single slice
    sl = 0
    T1est = T1est[..., sl]
    T2est = T2est[..., sl]
    dfest = dfest[..., sl]
    T1 = T1[..., sl]
    T2 = T2[..., sl]
    mask = mask[..., sl]

    # Simple phase unwrapping of off-resonance estimate
    dfest = unwrap_phase(dfest * 2 * np.pi * TR) / (2 * np.pi * TR)

    print('t1, mask:', T1.shape, mask.shape)

    nx, ny = 3, 3
    plt.subplot(nx, ny, 1)
    plt.imshow(T1 * mask)
    plt.title('T1 Truth')
    plt.axis('off')

    plt.subplot(nx, ny, 2)
    plt.imshow(T1est)
    plt.title('T1 est')
    plt.axis('off')

    plt.subplot(nx, ny, 3)
    plt.imshow(T1 * mask - T1est)
    plt.title('NRMSE: %g' % normalized_root_mse(T1, T1est))
    plt.axis('off')

    plt.subplot(nx, ny, 4)
    plt.imshow(T2 * mask)
    plt.title('T2 Truth')
    plt.axis('off')

    plt.subplot(nx, ny, 5)
    plt.imshow(T2est)
    plt.title('T2 est')
    plt.axis('off')

    plt.subplot(nx, ny, 6)
    plt.imshow(T2 * mask - T2est)
    plt.title('NRMSE: %g' % normalized_root_mse(T2, T2est))
    plt.axis('off')

    plt.subplot(nx, ny, 7)
    plt.imshow(df * mask)
    plt.title('df Truth')
    plt.axis('off')

    plt.subplot(nx, ny, 8)
    plt.imshow(dfest)
    plt.title('df est')
    plt.axis('off')

    plt.subplot(nx, ny, 9)
    plt.imshow(df * mask - dfest)
    plt.title('NRMSE: %g' % normalized_root_mse(df * mask, dfest))
    plt.axis('off')

    plt.show()
Example #14
0
    d, info = cg(A, b, x0=x0, maxiter=100)
    print(info)
    print(d.shape)

    return np.moveaxis(np.reshape(d, (nx, ny, nc)), -1, coil_axis)


if __name__ == '__main__':

    import matplotlib.pyplot as plt
    from phantominator import shepp_logan
    from utils import gaussian_csm

    N, nc = 128, 8
    ph = shepp_logan(N)[..., None] * gaussian_csm(N, N, nc)
    kspace = np.fft.ifftshift(np.fft.fft2(np.fft.fftshift(ph, axes=(0, 1)),
                                          axes=(0, 1)),
                              axes=(0, 1))

    # Get calibration region (20x20)
    pd = 10
    ctr = int(N / 2)
    calib = kspace[ctr - pd:ctr + pd, ctr - pd:ctr + pd, :].copy()

    # undersample by a factor of 2 in both kx and ky
    kspace[::2, 1::2, :] = 0
    kspace[1::2, ::2, :] = 0

    res = pruno(kspace, calib)
Example #15
0
import matplotlib.pyplot as plt
from skimage.metrics import normalized_root_mse
from phantominator import shepp_logan

from ssfp import bssfp, gs_recon, fimtre, planet

if __name__ == '__main__':

    fimtre_results = 1
    planet_results = 0
    sigma = 4e-5
    resid_mult = 10

    # Shepp-Logan
    N, nslices = 256, 1
    M0, T1, T2 = shepp_logan((N, N, nslices), MR=True, zlims=(-.25, 0))
    M0, T1, T2 = np.squeeze(M0), np.squeeze(T1), np.squeeze(T2)
    mask = np.abs(M0) > 1e-8

    # Simulate bSSFP acquisition with linear off-resonance
    TR0, TR1 = 3e-3, 6e-3
    alpha = np.deg2rad(80)
    alpha_lo = np.deg2rad(12)
    pcs8 = np.linspace(0, 2 * np.pi, 8, endpoint=False)
    pcs6 = np.linspace(0, 2 * np.pi, 6, endpoint=False)
    pcs4 = np.linspace(0, 2 * np.pi, 4, endpoint=False)
    pcs2 = np.linspace(0, 2 * np.pi, 2, endpoint=False)
    df, _ = np.meshgrid(np.linspace(-1 / (2 * TR1), 1 / (2 * TR1), N),
                        np.linspace(-1 / (2 * TR1), 1 / (2 * TR1), N))
    df *= mask
Example #16
0
'''Example demonstrating how to make a Shepp-Logan phantom.'''

import numpy as np
import matplotlib.pyplot as plt
from phantominator import shepp_logan

if __name__ == '__main__':

    # The original Shepp-Logan
    ph = shepp_logan(128, modified=False)
    plt.subplot(1, 2, 1)
    plt.title('Shepp-Logan')
    plt.imshow(ph, cmap='gray')

    # Modified Shepp-Logan for better contrast
    ph = shepp_logan(128, modified=True)
    plt.subplot(1, 2, 2)
    plt.title('Modified Shepp-Logan')
    plt.imshow(ph, cmap='gray')
    plt.show()

    # Generate phantoms with different sizes
    ph = shepp_logan((128, 256))
    plt.title('Strange sizes')
    plt.imshow(ph, cmap='gray')
    plt.show()

    # Get a 3D phantom
    ph = shepp_logan((128, 128, 20), zlims=(-.5, .5))

    # Fancy dancing to nicely show all slices on same plot
Example #17
0
'''Basic usage of CG-SENSE implementation.'''

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from phantominator import shepp_logan

from pygrappa import cgsense
from utils import gaussian_csm

if __name__ == '__main__':

    N, nc = 128, 4
    sens = gaussian_csm(N, N, nc)

    im = shepp_logan(N) + np.finfo('float').eps
    im = im[..., None] * sens
    kspace = np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(im, axes=(0, 1)),
                                         axes=(0, 1)),
                             axes=(0, 1))

    # Undersample
    kspace[::2, 1::2, :] = 0
    kspace[1::2, ::2, :] = 0

    # SOS of the aliased image
    aliased = np.fft.ifftshift(np.fft.ifft2(np.fft.fftshift(kspace,
                                                            axes=(0, 1)),
                                            axes=(0, 1)),
                               axes=(0, 1))
    aliased = np.sqrt(np.sum(np.abs(aliased)**2, axis=-1))
Example #18
0
from phantominator import shepp_logan
from skimage.metrics import normalized_root_mse as compare_nrmse  # pylint: disable=E0611,E0401

from pygrappa import vcgrappa, grappa
from utils import gaussian_csm

if __name__ == '__main__':

    # Simple phantom
    N = 128
    ncoil = 8
    _, phi = np.meshgrid(  # background phase variation
        np.linspace(-np.pi, np.pi, N), np.linspace(-np.pi, np.pi, N))
    phi = np.exp(1j * phi)
    csm = gaussian_csm(N, N, ncoil)
    ph = shepp_logan(N) * phi
    ph = ph[..., None] * csm

    # Throw into k-space
    ax = (0, 1)
    kspace = np.fft.ifftshift(np.fft.fft2(np.fft.fftshift(ph, axes=ax),
                                          axes=ax),
                              axes=ax)

    # 24 ACS lines
    pad = 12
    ctr = int(N / 2)
    calib = kspace[ctr - pad:ctr + pad, ...].copy()

    # R=4
    kspace[1::4, ...] = 0
Example #19
0
'''Show basic usage of spoiled GRE.'''

import numpy as np
import matplotlib.pyplot as plt
from phantominator import shepp_logan

from ssfp import spoiled_gre

if __name__ == '__main__':

    N = 128
    M0, T1, T2 = shepp_logan((N, N, 1), MR=True, zlims=(-.25, -.25))
    M0, T1, T2 = M0[..., 0], T1[..., 0], T2[..., 0]

    TR, TE = 0.035, 0.01
    alpha = np.deg2rad(70)
    res = spoiled_gre(T1, T2, TR, TE, alpha=alpha, M0=M0)

    plt.imshow(res)
    plt.show()
Example #20
0
import numpy as np
import matplotlib.pyplot as plt
from phantominator import shepp_logan
from skimage.measure import compare_nrmse

from pygrappa import cgrappa, grappaop
from utils import gaussian_csm

if __name__ == '__main__':

    # Make a simple phantom -- note that GRAPPA operator only works
    # well with pretty well separated coil sensitivities, so using
    # these simple maps we don't expect GRAPPA operator to work as
    # well as GRAPPA when trying to do "GRAPPA" things
    N, nc = 256, 16
    ph = shepp_logan(N)[..., None] * gaussian_csm(N, N, nc)

    # Put into kspace
    ax = (0, 1)
    kspace = np.fft.ifftshift(np.fft.fft2(np.fft.fftshift(ph, axes=ax),
                                          axes=ax),
                              axes=ax)

    # 20x20 calibration region
    ctr = int(N / 2)
    pad = 10
    calib = kspace[ctr - pad:ctr + pad, ctr - pad:ctr + pad, :].copy()

    # Undersample: R=4
    kspace4x1 = kspace.copy()
    kspace4x1[1::4, ...] = 0
Example #21
0
import numpy as np
import matplotlib.pyplot as plt
from phantominator import shepp_logan

from pygrappa import cgsense
from utils import gaussian_csm

if __name__ == '__main__':

    # Generate fake sensitivity maps: mps
    L, M, N = 128, 128, 32
    ncoils = 4
    mps = gaussian_csm(L, M, ncoils)[..., None, :]

    # generate 3D phantom
    ph = shepp_logan((L, M, N), zlims=(-.25, .25))
    imspace = ph[..., None] * mps
    ax = (0, 1, 2)
    kspace = np.fft.fftshift(np.fft.fftn(np.fft.ifftshift(imspace, axes=ax),
                                         axes=ax),
                             axes=ax)

    # undersample by a factor of 2 in both kx and ky
    kspace[::2, 1::2, ...] = 0
    kspace[1::2, ::2, ...] = 0

    # Do the recon
    t0 = time()
    res = cgsense(kspace, mps)
    print('Took %g sec' % (time() - t0))
Example #22
0
'''Basic demo of Slice-GRAPPA.'''

import numpy as np
from phantominator import shepp_logan
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

from pygrappa import slicegrappa
from utils import gaussian_csm

if __name__ == '__main__':

    # Get slices of 3D Shepp-Logan phantom
    N = 128
    ns = 2
    ph = shepp_logan((N, N, ns), zlims=(-.3, 0))

    # Apply some coil sensitivities
    ncoil = 8
    csm = gaussian_csm(N, N, ncoil)
    ph = ph[..., None, :]*csm[..., None]

    # Shift one slice FOV/2 (SMS-CAIPI)
    ph[..., -1] = np.fft.fftshift(ph[..., -1], axes=0)

    # Put into kspace
    ax = (0, 1)
    kspace = np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(
        ph, axes=ax), axes=ax), axes=ax)

    # Calibration data is individual slices
Example #23
0
if __name__ == '__main__':

    # Generate fake sensitivity maps: mps
    N = 128
    ncoils = 4
    xx = np.linspace(0, 1, N)
    x, y = np.meshgrid(xx, xx)
    mps = np.zeros((N, N, ncoils))
    mps[..., 0] = x**2
    mps[..., 1] = 1 - x**2
    mps[..., 2] = y**2
    mps[..., 3] = 1 - y**2

    # generate 4 coil phantom
    ph = shepp_logan(N)
    imspace = ph[..., None] * mps
    imspace = imspace.astype('complex')

    # Use NamedTemporaryFiles for kspace and reconstruction results
    with NTF() as kspace_file, NTF() as res_file:
        # Make a memmap
        kspace = np.memmap(kspace_file,
                           mode='w+',
                           shape=(N, N, ncoils),
                           dtype='complex')

        # Fill the memmap with kspace data (remember the [:]!!!)
        ax = (0, 1)
        kspace[:] = 1 / np.sqrt(N**2) * np.fft.fftshift(
            np.fft.fft2(np.fft.ifftshift(imspace, axes=ax), axes=ax), axes=ax)
Example #24
0
from phantominator import shepp_logan
from cv2 import imwrite

size_list = [256 * 2**i for i in range(3)]

if __name__ == '__main__':
    for size in size_list:
        sl = shepp_logan(size)
        sl = (sl * 255).astype(int)
        imwrite("res/shepp-logan{}.jpg".format(size), sl)