예제 #1
0
 def test_im2ksp_cart(self):
     # Image to k-space transformation for Cartesian data
     ksp = im2ksp(M=ph, cartesian_opt=1)
     self.assertEqual(ksp.shape, ph.shape)  # Dimensions agree
     self.assertEqual(
         ((ksp - cart_ksp) == np.zeros(ksp.shape).astype(complex)).all(),
         True)  # Transformation is correct
예제 #2
0
 def test_im2ksp_noncart(self):
     # Image to k-space transformation for non-Cartesian data
     nufft_obj = nufft_init(kt=ktraj, params=acq_params)
     ksp = im2ksp(
         M=ph, cartesian_opt=0, NufftObj=nufft_obj,
         params=acq_params)  # Sample the image along the trajectory
     self.assertEqual(ksp.shape, ktraj.shape)  # Dimensions match
예제 #3
0
def add_or(M, kt, df, nonCart=None, params=None):
    '''Forward model for off-resonance simulation

    Parameters
    ----------
    M : numpy.ndarray
        Image data
    kt : numpy.ndarray
        k-space trajectory
    df : numpy.ndarray
        Field map
    nonCart : int , optional
        Cartesian/Non-Cartesian trajectory option. Default is None.
    params : dict , optional
        Sequence parameters. Default is None.

    Returns
    -------
    M_or : numpy.ndarray
        Off-resonance corrupted image data
    '''
    '''Create a phase matrix - 2*pi*df*t for every df and every t'''
    if nonCart is not None:
        cartesian_opt = 0
        NufftObj = nufft_init(kt, params)

    else:
        cartesian_opt = 1
        NufftObj = None
        params = None

    kspace = im2ksp(M, cartesian_opt, NufftObj, params)
    M_or = np.zeros(M.shape, dtype=complex)

    for x in range(M.shape[0]):
        for y in range(M.shape[1]):
            phi = 2 * pi * df[x, y] * kt
            kspace_orc = kspace * np.exp(-1j * phi)
            M_corr = ksp2im(kspace_orc, cartesian_opt, NufftObj, params)
            M_or[x, y] = M_corr[x, y]

    return M_or
예제 #4
0
 def test_cartesian_opt(self):
     # cartesian_opt can only be 0 or 1, otherwise error
     with self.assertRaises(ValueError):
         im2ksp(M=ph, cartesian_opt=5)
     with self.assertRaises(ValueError):
         ksp2im(ksp=cart_ksp, cartesian_opt=100)
예제 #5
0
def MFI(dataIn, dataInType, kt, df, Lx, nonCart=None, params=None):
    '''Off-resonance Correction by Multi-Frequency Interpolation
    Man, L., Pauly, J. M. and Macovski, A. (1997), Multifrequency interpolation for fast off‐resonance correction. Magn. Reson. Med., 37: 785-792. doi:10.1002/mrm.1910370523

    Parameters
    ----------
    dataIn : numpy.ndarray
        k-space raw data or image data
    dataInType : str
        Can be either 'raw' or 'im'
    kt : numpy.ndarray
        k-space trajectory
    df : numpy.ndarray
        Field map
    Lx : int
        L (frequency bins) factor
    nonCart : int
        Non-cartesian trajectory option. Default is None (Cartesian).
    params : dict
        Sequence parameters. Default is None.
    Returns
    -------
    M_hat : numpy.ndarray
        Corrected image data.
    '''

    if nonCart is not None and nonCart == 1:
        check_inputs_noncartesian(dataIn.shape, dataInType, kt.shape, df.shape,
                                  params)
        cartesian_opt = 0
        NufftObj = nufft_init(kt, params)
        t_vector = params['t_vector']
        T = np.tile(params['t_vector'], (1, kt.shape[1]))
        t_ro = T[-1, 0] - T[0, 0]  # T[end] - TE
        N = params['N']

    elif nonCart == 'EPI':
        # check_inputs_cartesian(dataIn.shape, dataInType, kt.shape, df.shape)
        cartesian_opt = 1
        NufftObj = None
        T = np.flipud(params['t_vector']).reshape(params['N'], params['N'])
        T[1:params['N']:2, :] = np.fliplr(T[1:params['N']:2, :])
        N = dataIn.shape[0]
        t_ro = params['t_readout']
        t_vector = params['t_vector']

    else:
        check_inputs_cartesian(dataIn.shape, dataInType, kt.shape, df.shape)
        cartesian_opt = 1
        NufftObj = None
        N = dataIn.shape[0]

        t_vector = kt[0].reshape(kt.shape[1], 1)
        T = kt
        t_ro = T[0, -1] - T[0, 0]

    if dataInType == 'im':
        rawData = im2ksp(dataIn, cartesian_opt, NufftObj, params)
    elif dataInType == 'raw':
        rawData = dataIn

    df = np.round(df, 1)
    idx, idy = np.where(df == -0.0)
    df[idx, idy] = 0.0

    # Number of frequency segments
    df_max = max(np.abs([df.max(), df.min()]))  # Hz
    df_range = (df.min(), df.max())
    L = ceil(df_max * 2 * pi * t_ro / pi)
    L = L * Lx
    if len(np.unique(df)) == 1:
        L = 1
    f_L = np.linspace(df.min(), df.max(), L + 1)  # Hz

    #T = np.tile(params['t_vector'], (1, kt.shape[1]))

    # reconstruct the L basic images
    M_MFI = np.zeros((N, N, L + 1), dtype=complex)
    for l in range(L + 1):
        phi = 2 * pi * f_L[l] * T
        kspace_L = rawData * np.exp(1j * phi)
        M_MFI[:, :, l] = ksp2im(kspace_L, cartesian_opt, NufftObj, params)

    # calculate MFI coefficients
    coeffs_LUT = coeffs_MFI_lsq(kt, f_L, df_range, t_vector)

    # final image reconstruction
    M_hat = np.zeros((N, N), dtype=complex)
    for i in range(M_hat.shape[0]):
        for j in range(M_hat.shape[1]):
            fieldmap_val = df[i, j]
            val_coeffs = coeffs_LUT[str(fieldmap_val)]
            M_hat[i, j] = sum(val_coeffs * M_MFI[i, j, :])

    return M_hat
예제 #6
0
def fs_CPR(dataIn, dataInType, kt, df, Lx, nonCart=None, params=None):
    '''Off-resonance Correction by frequency-segmented Conjugate Phase Reconstruction
    Noll, D. C., Pauly, J. M., Meyer, C. H., Nishimura, D. G. and Macovskj, A. (1992), Deblurring for non‐2D fourier transform magnetic resonance imaging. Magn. Reson. Med., 25: 319-333. doi:10.1002/mrm.1910250210

    Parameters
    ----------
    dataIn : numpy.ndarray
        k-space raw data or image data
    dataInType : str
        Can be either 'raw' or 'im'
    kt : numpy.ndarray
        k-space trajectory
    df : numpy.ndarray
        Field map
    Lx : int
        L (frequency bins) factor
    nonCart : int
        Non-cartesian trajectory option. Default is None (Cartesian).
    params : dict
        Sequence parameters. Default is None (Cartesian).

    Returns
    -------
    M_hat : numpy.ndarray
        Corrected image data.
    '''
    if nonCart is not None and nonCart == 1:
        check_inputs_noncartesian(dataIn.shape, dataInType, kt.shape, df.shape,
                                  params)

        cartesian_opt = 0
        NufftObj = nufft_init(kt, params)
        T = np.tile(params['t_vector'], (1, kt.shape[1]))

        N = params['N']
        t_ro = T[-1, 0] - T[0, 0]  # T[end] - TE

    elif nonCart == 'EPI':
        # check_inputs_cartesian(dataIn.shape, dataInType, kt.shape, df.shape)
        cartesian_opt = 1
        NufftObj = None
        T = np.flipud(params['t_vector']).reshape(params['N'], params['N'])
        T[1:params['N']:2, :] = np.fliplr(T[1:params['N']:2, :])
        N = dataIn.shape[0]
        t_ro = params['t_readout']

    else:
        check_inputs_cartesian(dataIn.shape, dataInType, kt.shape, df.shape)
        cartesian_opt = 1
        NufftObj = None
        N = dataIn.shape[0]

        t_vector = kt[0].reshape(kt.shape[1], 1)
        T = kt
        t_ro = T[0, -1] - T[0, 0]

    if dataInType == 'im':
        rawData = im2ksp(dataIn, cartesian_opt, NufftObj, params)
    elif dataInType == 'raw':
        rawData = dataIn

    # Number of frequency segments
    df_max = max(np.abs([df.max(), df.min()]))  # Hz
    L = ceil(4 * df_max * 2 * pi * t_ro / pi)
    L = L * Lx
    if len(np.unique(df)) == 1:
        L = 1
    f_L = np.linspace(df.min(), df.max(), L + 1)  # Hz

    # T = np.tile(params['t_vector'], (1, kt.shape[1]))

    # reconstruct the L basic images
    M_fsCPR = np.zeros((N, N, L + 1), dtype=complex)
    for l in range(L + 1):
        phi = 2 * pi * f_L[l] * T
        kspace_L = rawData * np.exp(1j * phi)
        M_fsCPR[:, :, l] = ksp2im(kspace_L, cartesian_opt, NufftObj, params)

    # final image reconstruction
    M_hat = np.zeros((N, N), dtype=complex)
    for i in range(M_hat.shape[0]):
        for j in range(M_hat.shape[1]):
            fieldmap_val = df[i, j]
            closest_fL_idx = find_nearest(f_L, fieldmap_val)

            if fieldmap_val == f_L[closest_fL_idx]:
                pixel_val = M_fsCPR[i, j, closest_fL_idx]
            else:
                if fieldmap_val < f_L[closest_fL_idx]:
                    f_vals = [f_L[closest_fL_idx - 1], f_L[closest_fL_idx]]
                    im_vals = [
                        M_fsCPR[i, j, closest_fL_idx - 1],
                        M_fsCPR[i, j, closest_fL_idx]
                    ]
                else:
                    f_vals = [f_L[closest_fL_idx], f_L[closest_fL_idx + 1]]
                    im_vals = [
                        M_fsCPR[i, j, closest_fL_idx],
                        M_fsCPR[i, j, closest_fL_idx + 1]
                    ]

                pixel_val = np.interp(fieldmap_val, f_vals, im_vals)

            M_hat[i, j] = pixel_val

    return M_hat
예제 #7
0
def CPR(dataIn, dataInType, kt, df, nonCart=None, params=None):
    '''Off-resonance Correction by Conjugate Phase Reconstruction
    Maeda, A., Sano, K. and Yokoyama, T. (1988), Reconstruction by weighted correlation for MRI with time-varying gradients. IEEE Transactions on Medical Imaging, 7(1): 26-31. doi: 10.1109/42.3926

    Parameters
    ----------
    dataIn : numpy.ndarray
        k-space raw data or image data
    dataInType : str
        Can be either 'raw' or 'im'
    kt : numpy.ndarray
        k-space trajectory.
    df : numpy.ndarray
        Field map
    nonCart : int
        Non-cartesian trajectory option. Default is None (Cartesian).
    params : dict
        Sequence parameters. Default is None (Cartesian).

    Returns
    -------
    M_hat : numpy.ndarray
        Corrected image data.
    '''

    if nonCart is not None and nonCart == 1:
        check_inputs_noncartesian(dataIn.shape, dataInType, kt.shape, df.shape,
                                  params)
        cartesian_opt = 0
        NufftObj = nufft_init(kt, params)
        T = np.tile(params['t_vector'], (1, kt.shape[1]))
        N = params['N']

    elif nonCart == 'EPI':
        # check_inputs_cartesian(dataIn.shape, dataInType, kt.shape, df.shape)
        cartesian_opt = 1
        NufftObj = None
        T = np.flipud(params['t_vector']).reshape(params['N'], params['N'])
        T[1:params['N']:2, :] = np.fliplr(T[1:params['N']:2, :])

        N = dataIn.shape[0]

    else:
        check_inputs_cartesian(dataIn.shape, dataInType, kt.shape, df.shape)
        cartesian_opt = 1
        NufftObj = None
        T = kt
        N = dataIn.shape[0]

    if dataInType == 'im':
        rawData = im2ksp(dataIn, cartesian_opt, NufftObj, params)
    elif dataInType == 'raw':
        rawData = dataIn

    df_values = np.unique(df)
    M_CPR = np.zeros((N, N, len(df_values)), dtype=complex)
    for i in range(len(df_values)):
        phi = 2 * pi * df_values[i] * T
        kspace_orc = rawData * np.exp(1j * phi)
        M_corr = ksp2im(kspace_orc, cartesian_opt, NufftObj, params)
        M_CPR[:, :, i] = M_corr

    M_hat = np.zeros((N, N), dtype=complex)
    for x in range(df.shape[0]):
        for y in range(df.shape[1]):
            fieldmap_val = df[x, y]
            idx = np.where(df_values == fieldmap_val)
            M_hat[x, y] = M_CPR[x, y, idx]

    return M_hat
예제 #8
0
def add_or_CPR(M, kt, df, nonCart=None, params=None):
    '''Forward model for off-resonance simulation. The number of fourier transforms = number of unique values in the field map.

    Parameters
    ----------
    M : numpy.ndarray
        Image data
    kt : numpy.ndarray
        k-space trajectory
    df : numpy.ndarray
        Field map
    nonCart : int , optional
        Cartesian/Non-Cartesian trajectory option. Default is None.
    params : dict , optional
        Sequence parameters. Default is None.

    Returns
    -------
    M_or : numpy.ndarray
        Off-resonance corrupted image data
    '''
    # Create a phase matrix - 2*pi*df*t for every df and every t
    if nonCart is not None and nonCart == 1:
        cartesian_opt = 0
        NufftObj = nufft_init(kt, params)
        T = np.tile(params['t_vector'], (1, kt.shape[1]))

    elif nonCart == 'EPI':
        cartesian_opt = 1
        NufftObj = None
        T = np.flipud(params['t_vector']).reshape(params['N'], params['N'])
        T[1:params['N']:2, :] = np.fliplr(T[1:params['N']:2, :])

    else:
        cartesian_opt = 1
        NufftObj = None
        params = None
        T = kt

    kspace = im2ksp(M, cartesian_opt, NufftObj, params)

    df_values = np.unique(df)

    M_or_CPR = np.zeros((M.shape[0], M.shape[1], len(df_values)),
                        dtype=complex)
    kspsave = np.zeros((kspace.shape[0], kspace.shape[1], len(df_values)),
                       dtype=complex)
    for i in range(len(df_values)):
        phi = -2 * pi * df_values[i] * T
        kspace_or = kspace * np.exp(1j * phi)
        kspsave[:, :, i] = kspace_or
        M_corr = ksp2im(kspace_or, cartesian_opt, NufftObj, params)
        M_or_CPR[:, :, i] = M_corr

    M_or = np.zeros(M.shape, dtype=complex)
    for x in range(M.shape[0]):
        for y in range(M.shape[1]):
            fieldmap_val = df[x, y]
            idx = np.where(df_values == fieldmap_val)
            M_or[x, y] = M_or_CPR[x, y, idx]
    '''plt.imshow(abs(M_or))
    plt.show()'''
    return M_or, kspsave