Beispiel #1
0
    def test_cross_point(self):
        from mr_utils.sim.ssfp import ssfp, get_cross_point, get_complex_cross_point

        # Get four phase cycled images
        I1 = ssfp(self.T1, self.T2, self.TR, self.alpha, self.df, phase_cyc=0)
        I2 = ssfp(self.T1,
                  self.T2,
                  self.TR,
                  self.alpha,
                  self.df,
                  phase_cyc=np.pi / 2)
        I3 = ssfp(self.T1,
                  self.T2,
                  self.TR,
                  self.alpha,
                  self.df,
                  phase_cyc=np.pi)
        I4 = ssfp(self.T1,
                  self.T2,
                  self.TR,
                  self.alpha,
                  self.df,
                  phase_cyc=3 * np.pi / 2)

        # Find cross points
        x0, y0 = get_cross_point(I1, I2, I3, I4)
        M = get_complex_cross_point(I1, I2, I3, I4)

        # Make sure we get the same answer
        self.assertTrue(np.allclose(x0 + 1j * y0, M))
Beispiel #2
0
    def test_many_phase_cycles_single_point(self):
        '''Make sure we can do a bunch of them at once.'''

        pcs = np.linspace(0, 2 * np.pi, 16, endpoint=False)
        Itrue = np.zeros(pcs.size, dtype='complex')
        for ii, pc in np.ndenumerate(pcs):
            Itrue[ii] = ssfp(self.T1, self.T2, self.TR, self.alpha, self.df,
                             pc)

        Is = ssfp(self.T1, self.T2, self.TR, self.alpha, self.df, pcs)
        self.assertTrue(np.allclose(Itrue, Is))
Beispiel #3
0
    def test_two_phase_cycles_single_point(self):
        '''Try doing two phase-cycles.'''

        # Gold standard is computing them individually
        pcs = np.linspace(0, 2 * np.pi, 2, endpoint=False)
        I0 = ssfp(self.T1, self.T2, self.TR, self.alpha, self.df, pcs[0])
        I1 = ssfp(self.T1, self.T2, self.TR, self.alpha, self.df, pcs[1])
        Itrue = np.stack((I0, I1))

        # Now try all at once
        Is = ssfp(self.T1, self.T2, self.TR, self.alpha, self.df, pcs)

        self.assertTrue(np.allclose(Itrue, Is))
    def test_simulated_field_maps(self):
        '''Simulate the field maps and see if we can recover them.'''

        # Get quantitative MR maps
        T1 = 1.
        T2 = .8
        PD = 1
        TR = 6e-3
        alpha = np.deg2rad(10)
        phase_cyc = 0

        # Monte Carlo: find the response that matches Mxy most closely
        num_sims = 1000
        err = 0
        tol = 1.
        beta = 1  # don't simulate df on the boundaries of the profile...
        dfs = np.arange(-1 / TR, 1 / TR, .1)  # Do for all possible df
        for _ii in trange(num_sims, leave=False, desc='Monte Carlo'):

            # Measure the signal in the real off-resonance environment
            df_true = np.random.uniform(low=-1 / TR + beta, high=1 / TR - beta)
            Mxy = ssfp(T1, T2, TR, alpha, df_true, phase_cyc=phase_cyc, M0=PD)

            # Find closest match and take that to be the off-resonance value
            df0 = quantitative_fm(Mxy, dfs, T1, T2, PD, TR, alpha, phase_cyc)
            if np.abs(df_true - df0) > tol:
                print('True: %g, found: %g' % (df_true, df0))
                err += 1

        self.assertFalse(err)
Beispiel #5
0
def ssfp_dictionary_for_loop(T1s, T2s, TR, alphas, df):
    '''Verification for ssfp_dictionary generation.

    Parameters
    ==========
    T1s : array_like
        (1D) all T1 decay constant values to simulate.
    T2s : array_like
        (1D) all T2 decay constant values to simulate.
    TR : float
        repetition time for bSSFP simulation.
    alphas : array_like
        (1D) all flip angle values to simulate.
    df : array_like
        (1D) off-resonance frequencies over which to simulate.

    Returns
    =======
    D : array_like
        Dictionary of simulated values
    keys : array_like
        Keys of dictionary D, all (T1, T2, alpha) combinations.
    '''

    # Get keys from supplied params
    keys = get_keys(T1s, T2s, alphas)

    # Generate dictionary iterating over keys
    N = keys.shape[1]
    D = np.zeros((N, df.size), dtype='complex')
    for ii in range(N):
        for jj in range(df.size):
            D[ii, jj] = ssfp(keys[0, ii], keys[1, ii], TR, keys[2, ii], df[jj])
    return (D, keys)
Beispiel #6
0
    def test_banding_sim_2d(self):
        '''Make sure banding looks the same coming from NMR params and ESM.'''

        # To get periodic banding like we want to see, we need some serious
        # field inhomogeneity.
        dim = 256
        min_df, max_df = 0, 500
        x = np.linspace(min_df, max_df, dim)
        y = np.zeros(dim)
        field_map, _ = np.meshgrid(x, y)

        # # Show the field map
        # plt.imshow(field_map)
        # plt.show()

        # # Generate simulated banding image explicitly using NMR parameters
        sig0 = ssfp(self.T1, self.T2, self.TR, self.alpha, field_map)
        # plt.subplot(2,1,1)
        # plt.imshow(np.abs(sig0))
        # plt.subplot(2,1,2)
        # plt.plot(np.abs(sig0[int(dim/2),:]))
        # plt.show()

        # Generate simulated banding image using elliptical signal model
        M, a, b = elliptical_params(self.T1, self.T2, self.TR, self.alpha)
        sig1 = ssfp_from_ellipse(M, a, b, self.TR, field_map)

        self.assertTrue(np.allclose(sig0, sig1))
def get_df_responses(T1, T2, PD, TR, alpha, phase_cyc, dfs):
    '''Simulate bSSFP response across all possible off-resonances.

    Parameters
    ==========
    T1 : float
        scalar T1 longitudinal recovery value in seconds.
    T2 : float
        scalar T2 transverse decay value in seconds.
    PD : float
        scalar proton density value scaled the same as acquisiton.
    TR : float
        Repetition time in seconds.
    alpha : float
        Flip angle in radians.
    phase_cyc : float
        RF phase cycling in radians.
    dfs : float
        Off-resonance values to simulate over.

    Returns
    =======
    resp : array_like
        Frequency response of SSFP signal across entire spectrum.
    '''

    # Feed ssfp sim an array of parameters to be used with all the df values
    T1s = np.ones(dfs.shape) * T1
    T2s = np.ones(dfs.shape) * T2
    PDs = np.ones(dfs.shape) * PD
    resp = ssfp(T1s, T2s, TR, alpha, dfs, phase_cyc=phase_cyc, M0=PDs)

    # Returns a vector of simulated Mxy with index corresponding to dfs
    return resp
Beispiel #8
0
    def setUp(self):
        from mr_utils.sim.ssfp import ssfp

        self.TR = 6e-3
        self.T1, self.T2 = 1, .8
        self.alpha = np.pi / 3

        # To get periodic banding like we want to see, we need some serious
        # field inhomogeneity.
        dim = 256
        min_df, max_df = 0, 500
        x = np.linspace(min_df, max_df, dim)
        y = np.zeros(dim)
        self.field_map, _ = np.meshgrid(x, y)

        # Get four phase cycled images
        self.I1 = ssfp(self.T1,
                       self.T2,
                       self.TR,
                       self.alpha,
                       self.field_map,
                       phase_cyc=0)
        self.I2 = ssfp(self.T1,
                       self.T2,
                       self.TR,
                       self.alpha,
                       self.field_map,
                       phase_cyc=np.pi / 2)
        self.I3 = ssfp(self.T1,
                       self.T2,
                       self.TR,
                       self.alpha,
                       self.field_map,
                       phase_cyc=np.pi)
        self.I4 = ssfp(self.T1,
                       self.T2,
                       self.TR,
                       self.alpha,
                       self.field_map,
                       phase_cyc=3 * np.pi / 2)
        self.Is = ssfp(self.T1,
                       self.T2,
                       self.TR,
                       self.alpha,
                       self.field_map,
                       phase_cyc=[0, np.pi / 2, np.pi, 3 * np.pi / 2])
Beispiel #9
0
def bssfp_2d_cylinder(TR=6e-3,
                      alpha=np.pi / 3,
                      dims=(64, 64),
                      FOV=((-1, 1), (-1, 1)),
                      radius=.5,
                      field_map=None,
                      phase_cyc=0,
                      kspace=False):
    '''Simulates axial bSSFP scan of cylindrical phantom.

    Parameters
    ----------
    TR : float, optional
        Repetition time.
    alpha : float, optional
        Flip angle (in rad).
    dims : tuple of ints, optional
        Matrix size, (dim_x,dim_y)
    FOV : tuple of tuples, optional
        Field of view in arbitrary units:
        ( (x_min,x_max), (y_min,y_max) )
    radius : float, optional
        Radius of cylinder in arbitrary units.
    field_map : array_like, optional
        (dim_x,dim_y) field map. If None, linear gradient in x used.
    phase_cyc : float, optional
        Phase cycling used in simulated bSSFP acquisition (in rad).
    kspace : bool, optional
        Whether or not to return data in kspace or imspace.

    Returns
    -------
    im : array_like
        Complex simulated image with bSSFP contrast.
    '''

    # Get the base cylinder maps
    PD, T1s, T2s = cylinder_2d(dims=dims, FOV=FOV, radius=radius)

    if field_map is None:
        min_df, max_df = 0, 500
        fx = np.linspace(min_df, max_df, dims[0])
        fy = np.zeros(dims[1])
        field_map, _ = np.meshgrid(fx, fy)

    im = ssfp(T1s, T2s, TR, alpha, field_map, phase_cyc=phase_cyc, M0=PD).T
    # im = gre_sim(T1s,T2s,TR,TR/2,alpha,field_map,phi=phase_cyc,
    #              dphi=phase_cyc,M0=PD,spoil=False,iter=200)
    # im[np.isnan(im)] = 0
    # view(im)

    if kspace:
        return np.fft.fftshift(np.fft.fft2(np.fft.fftshift(im), axes=(0, 1)),
                               axes=(0, 1))
    #else...
    return im
Beispiel #10
0
    def test_gre_unspoiled_and_bssfp(self):
        '''Very balanced steady state solution.'''
        M0, T1, T2 = 5.0, 1.0, .5
        im1 = gre_sim(T1, T2, TR=self.TR, TE=self.TR/2, alpha=self.alpha,
                      field_map=np.zeros(1), M0=M0, spoil=False, maxiter=200)
        im2 = ssfp(T1, T2, TR=self.TR, alpha=self.alpha, field_map=np.zeros(1),
                   phase_cyc=0, M0=M0)

        # Currently failing...
        self.assertEqual(im1, im2)
Beispiel #11
0
    def test_find_atom(self):
        from mr_utils.sim.ssfp import ssfp, ssfp_dictionary, find_atom

        D, keys = ssfp_dictionary(self.T1s, self.T2s, self.TR, self.alphas,
                                  self.df)
        sig = ssfp(self.T10, self.T20, self.TR, self.alpha0, self.df)
        found_params = find_atom(sig, D, keys)
        actual_params = np.array([self.T10, self.T20, self.alpha0])

        self.assertTrue(np.allclose(actual_params, found_params))
Beispiel #12
0
    def test_gs(self):
        from mr_utils.sim.ssfp import ssfp
        from mr_utils.recon.ssfp import gs_recon

        pcs = np.zeros((4, self.dim, self.dim), dtype='complex')
        for ii, pc in enumerate([0, np.pi / 2, np.pi, 3 * np.pi / 2]):
            pcs[ii, ...] = ssfp(**self.args, phase_cyc=pc)
        # view(pcs)

        recon = gs_recon(*[x.squeeze() for x in np.split(pcs, 4)])
Beispiel #13
0
    def test_find_atom(self):
        '''Test method that finds atom in a given dictionary.'''

        D, keys = ssfp_dictionary(self.T1s, self.T2s, self.TR, self.alphas,
                                  self.df)
        sig = ssfp(self.T10, self.T20, self.TR, self.alpha0, self.df)
        found_params = find_atom(sig, D, keys)
        actual_params = np.array([self.T10, self.T20, self.alpha0])

        self.assertTrue(np.allclose(actual_params, found_params))
Beispiel #14
0
    def test_ssfp_sim(self):
        '''Generate signal from bSSFP signal eq and elliptical model.'''

        # Do it the "normal" way
        I0 = ssfp(self.T1, self.T2, self.TR, self.alpha, self.df)

        # Now do it using the elliptical model
        M, a, b = elliptical_params(self.T1, self.T2, self.TR, self.alpha)
        I1 = ssfp_from_ellipse(M, a, b, self.TR, self.df)

        self.assertTrue(np.allclose(I0, I1))
Beispiel #15
0
    def test_ssfp_sim(self):
        from mr_utils.sim.ssfp import ssfp, get_theta, elliptical_params, ssfp_from_ellipse

        # Do it the "normal" way
        I0 = ssfp(self.T1, self.T2, self.TR, self.alpha, self.df)

        # Now do it using the elliptical model
        M, a, b = elliptical_params(self.T1, self.T2, self.TR, self.alpha)
        I1 = ssfp_from_ellipse(M, a, b, self.TR, self.df)

        self.assertTrue(np.allclose(I0, I1))
Beispiel #16
0
    def test_t1_t2_field_map_mats(self):
        from mr_utils.sim.ssfp import ssfp

        # Let T1,T2, and field_map all be matrices over the entire 2d image
        sig = ssfp(self.T1s,
                   self.T2s,
                   self.TR,
                   self.alpha,
                   self.field_map,
                   phase_cyc=0,
                   M0=self.PD)
Beispiel #17
0
def plotEllipse(T1, T2, TR, alpha, offres, M0, dphi):
    '''Compute (x, y) coordinates for ellipse described by MR parameters.

    Parameters
    ==========
    T1 : float
        Longitudinal relaxation constant (in sec).
    T2 : float
        Transverse relaxation constant (in sec).
    TR : float
        Repetition time (in sec).
    alpha : float
        Flip angle (in rad).
    offres : float
        Off-resonance (in Hz).
    M0 : float
        Proton density.
    dphi : float or bool
        Phase-cycle value (in rad). dphi=True means use fixed linspace for dphi
        set, else, use the list of dphis provided.

    Returns
    =======
    x : array_like
        x coordinate values of ellipse.
    y : array_like
        y coordinate values of ellipse.
    '''

    if isinstance(dphi, bool):
        dphis = np.arange(0, 2 * np.pi, .01)
        Mxy = ssfp(T1, T2, TR, alpha, offres, phase_cyc=dphis, M0=M0)
    else:
        Mxy = ssfp(T1, T2, TR, alpha, offres, phase_cyc=dphis, M0=M0)

    x = Mxy.real
    y = Mxy.imag
    return (x, y)
Beispiel #18
0
def bssfp_acq(T1s,
              T2s,
              PD,
              field_map,
              TR=5e-3,
              alpha=np.deg2rad(10),
              phase_cyc=0):
    return (ssfp(T1s,
                 T2s,
                 TR,
                 alpha,
                 field_map=field_map,
                 phase_cyc=phase_cyc,
                 M0=PD))
Beispiel #19
0
    def test_two_phase_cycles_multiple_point(self):
        '''Now make MxN param maps and simulate multiple phase-cycles.'''

        M, N = 10, 5
        T1s = np.ones((M, N)) * self.T1
        T2s = np.ones((M, N)) * self.T2
        alphas = np.ones((M, N)) * self.alpha

        # Linear gradient for field map
        min_df, max_df = 0, 200
        fx = np.linspace(min_df, max_df, N)
        fy = np.zeros(M)
        df, _ = np.meshgrid(fx, fy)

        # Gold standard is again, computing individually
        pcs = np.linspace(0, 2 * np.pi, 2, endpoint=False)
        I0 = ssfp(T1s, T2s, self.TR, alphas, df, pcs[0])
        I1 = ssfp(T1s, T2s, self.TR, alphas, df, pcs[1])
        Itrue = np.stack((I0, I1))

        # Now try doing all at once
        # reps = (pcs.size, 1, 1)
        # pcs = np.tile(pcs, T1s.shape[:] + (1,)).transpose((2, 0, 1))
        # T1s = np.tile(T1s, reps)
        # T2s = np.tile(T2s, reps)
        # alphas = np.tile(alphas, reps)
        # df = np.tile(df, reps)
        # print(T1s.shape, T2s.shape, alphas.shape, df.shape, pcs.shape)

        Is = ssfp(T1s, T2s, self.TR, alphas, df, pcs)

        # from mr_utils import view
        # view(np.vstack((Itrue, Is)))

        # print(Itrue.shape, Is.shape)

        self.assertTrue(np.allclose(Itrue, Is))
Beispiel #20
0
 def setUp(self):
     self.num_pc = 6
     self.pcs = [2 * np.pi * n / self.num_pc for n in range(self.num_pc)]
     self.TR = 10e-3
     self.alpha = np.deg2rad(30)
     self.df = 1 / (5 * self.TR)
     self.T1 = 1.5
     self.T2 = .8
     self.T1s = np.linspace(.2, 2, 100)
     self.I = ssfp(self.T1,
                   self.T2,
                   self.TR,
                   self.alpha,
                   self.df,
                   phase_cyc=self.pcs)
Beispiel #21
0
def bssfp_acq(T1s,
              T2s,
              PD,
              field_map,
              TR=5e-3,
              alpha=np.deg2rad(10),
              phase_cyc=0):
    '''Wrapper to simulate bSSFP acquisition.'''
    return ssfp(T1s,
                T2s,
                TR,
                alpha,
                field_map=field_map,
                phase_cyc=phase_cyc,
                M0=PD)
Beispiel #22
0
    def test_cross_point(self):
        '''Find cross point from cartesian and ESM function.'''

        # Get four phase cycled images
        I1 = ssfp(self.T1, self.T2, self.TR, self.alpha, self.df, phase_cyc=0)
        I2 = ssfp(self.T1,
                  self.T2,
                  self.TR,
                  self.alpha,
                  self.df,
                  phase_cyc=np.pi / 2)
        I3 = ssfp(self.T1,
                  self.T2,
                  self.TR,
                  self.alpha,
                  self.df,
                  phase_cyc=np.pi)
        I4 = ssfp(self.T1,
                  self.T2,
                  self.TR,
                  self.alpha,
                  self.df,
                  phase_cyc=3 * np.pi / 2)
        Is = ssfp(self.T1,
                  self.T2,
                  self.TR,
                  self.alpha,
                  self.df,
                  phase_cyc=[0, np.pi / 2, np.pi, 3 * np.pi / 2])

        # Find cross points
        x0, y0 = get_cross_point(I1, I2, I3, I4)
        M = get_complex_cross_point(Is)

        # Make sure we get the same answer
        self.assertTrue(np.allclose(x0 + 1j * y0, M))
Beispiel #23
0
def ssfp_dictionary(T1s, T2s, TR, alphas, df):
    '''Generate a dicionary of bSSFP profiles given parameters.

    Parameters
    ==========
    T1s : array_like
        (1D) all T1 decay constant values to simulate.
    T2s : array_like
        (1D) all T2 decay constant values to simulate.
    TR : float
        repetition time for bSSFP simulation.
    alphas : array_like
        (1D) all flip angle values to simulate.
    df : array_like
        (1D) off-resonance frequencies over which to simulate.

    Returns
    =======
    D : array_like
        Dictionary of simulated values
    keys : array_like
        Keys of dictionary D, all (T1, T2, alpha) combinations.

    Notes
    =====
    T1s,T2s,alphas should all be 1D arrays.  All feasible combinations will be
    simulated (i.e., where T1 >= T2).  The dictionary and keys are returned.
    Each dictionary column is the simulation over frequencies df.  The keys are
    a list of tuples: (T1,T2,alpha).
    '''

    # Get keys from supplied params
    keys = get_keys(T1s, T2s, alphas)

    # # Use more efficient matrix formulation
    # D = ssfp_old(keys[0, :], keys[1, :], TR, keys[2, :], df)

    # Right now we have to do it for every alpha because ssfp() can't handle
    # more than one alpha at a time...
    D = np.zeros((keys.shape[1], df.size), dtype='complex')
    for ii, alpha in np.ndenumerate(keys[2, :]):
        D[ii, :] = ssfp(keys[0, ii], keys[1, ii], TR, alpha, df)

    # D = np.zeros((keys.shape[1], df.size), dtype='complex')
    # for ii, alpha in np.ndenumerate(keys[2, :]):
    #     for jj, df0 in  np.ndenumerate(df):
    #         D[ii, jj] = ssfp(keys[0, ii], keys[1, ii], TR, alpha, df0)
    return (D, keys)
Beispiel #24
0
def get_df_responses(T1, T2, PD, TR, alpha, phase_cyc, dfs):
    '''Simulate bSSFP response across all possible off-resonances.

    T1 -- scalar T1 longitudinal recovery value in seconds.
    T2 -- scalar T2 transverse decay value in seconds.
    PD -- scalar proton density value scaled the same as acquisiton.
    TR -- Repetition time in seconds.
    alpha -- Flip angle in radians.
    phase_cyc -- RF phase cycling in radians.
    dfs -- Off-resonance values to simulate over.
    '''

    # Feed ssfp sim an array of parameters to be used with all the df values
    T1s = np.ones(dfs.shape) * T1
    T2s = np.ones(dfs.shape) * T2
    PDs = np.ones(dfs.shape) * PD
    resp = ssfp(T1s, T2s, TR, alpha, dfs, phase_cyc=phase_cyc, M0=PDs)

    # Returns a vector of simulated Mxy with index corresponding to dfs
    return (resp)
Beispiel #25
0
def runner(enum, T1, T2, TR, df, pcs, M0):
    '''Run PLANET fitting for the current iteration.'''
    idx = enum[0]
    nom_alpha, dev_alpha = enum[1][:]
    I = ssfp(T1, T2, TR, nom_alpha * (1 + dev_alpha), df, pcs, M0)

    try:
        _Meff, T10, T20 = PLANET(I, nom_alpha, TR, T1, disp=False)
        T1s = T10
        T2s = T20
    except AssertionError as _e:
        # tqdm.write(str(e))
        T1s = np.nan
        T2s = np.nan
    except ValueError as _e:
        # tqdm.write(str(e))
        T1s = np.nan
        T2s = np.nan
    except TypeError as _e:
        # tqdm.write(str(e))
        T1s = np.nan
        T2s = np.nan

    return (idx, T1s, T2s)
Beispiel #26
0
def ellipticalfit(Ireal, TR, dphis, offres, M0, alpha, T1, T2):
    '''ELLIPTICALFIT

    Parameters
    ==========
    Ireal : array_like
        Hermtian transposed phase-cycle values for single pixel.
    TR : float
        Repetition time (in sec).
    M0 :
        Estmated proton density from the band reduction algorithm.
    phasecycles :
        Phase-cycles (in rad).
    offres :
        Off-resonance estimation (in Hz).

    Returns
    =======
    J : array_like
        Real part of difference concatenated with imaginary part of difference
    '''

    I = ssfp(T1, T2, TR, alpha, offres, phase_cyc=dphis, M0=M0)
    return (I - Ireal).view(dtype=c_double)
Beispiel #27
0
if __name__ == '__main__':

    # SSFP experiment params
    TR = 12e-3
    alpha = np.deg2rad(10)
    lpcs = 64
    pcs = np.linspace(-2 * np.pi, 2 * np.pi, lpcs, endpoint=False)

    # Experiment conditions and tissue params
    T1 = .830
    T2 = .080
    M0 = 1
    dfs = np.linspace(-1 / TR, 1 / TR, lpcs, endpoint=False)

    # Do the thing once with no phi_rf, once with to see difference
    I = ssfp(T1, T2, TR, alpha, 0, pcs, M0, phi_rf=0)
    Idf = ssfp(T1, T2, TR, alpha, dfs, 0, M0, phi_rf=0)

    # Look at the spectral profile
    pcs_deg = np.rad2deg(pcs)
    aI = np.angle(I)
    aIdf = np.unwrap(np.angle(Idf)[::-1])[::-1]

    fig, ax1 = plt.subplots()
    ax1.plot(pcs_deg, np.abs(I))
    ax1.plot(pcs_deg, np.abs(Idf), '--')
    ax1.set_ylabel('Magnitude')
    ax1.set_xlabel('Frequency (deg)')

    ax2 = ax1.twinx()
    ax2.plot(pcs_deg, aI, '--', label='Phase, pcs')
Beispiel #28
0
    TR = 5e-3
    alpha = np.deg2rad(10)
    npcs = 64
    pcs = np.linspace(0, 2 * np.pi, npcs, endpoint=False)
    # pcs = 0

    # Tissue parameters
    T1 = 1.2
    T2 = .035
    M0 = 1
    df = 0
    # df = np.linspace(-1/TR, 1/TR, npcs, endpoint=False)
    phi_rf = np.deg2rad(0)

    # Simulate acquisition of phase-cycles for a single voxel
    I = ssfp(T1, T2, TR, alpha, df, pcs, M0, phi_rf=phi_rf)

    # # Take a gander
    # fig, ax1 = plt.subplots()
    # ax2 = ax1.twinx()
    # ax1.plot(np.abs(I), label='Magnitude')
    # ax2.plot(np.rad2deg(np.angle(I)), '--', label='Phase')
    # ax1.legend()
    # ax1.set_ylabel('Magnitude')
    # ax2.legend()
    # ax2.set_ylabel('Phase')
    # plt.show()

    # # Make a box
    # box = np.zeros(npcs)
    # box[int(npcs/4):-int(npcs/4)] = 1
Beispiel #29
0
    # Get a 2D image, since we can't seem to replicate using a single
    # voxel
    N = 64
    df_noise_std = 0
    radius = .8
    TR = 6e-3
    alpha = np.deg2rad(30)
    npcs = 4
    pcs = np.linspace(0, 2*np.pi, npcs, endpoint=False)
    PD, T1, T2 = cylinder_2d(dims=(N, N), radius=radius)

    df = 1000
    min_df, max_df = -df, df
    fx = np.linspace(min_df, max_df, N)
    fy = np.zeros(N)
    df, _ = np.meshgrid(fx, fy)

    if df_noise_std > 0:
        n = np.random.normal(0, df_noise_std, df.shape)
        df += n

    I = ssfp(T1, T2, TR, alpha, df, pcs, PD, phi_rf=0)


    recon = gs_recon(I, pc_axis=0)
    recon_no_second = gs_recon(I, pc_axis=0, second_pass=False)

    I0 = np.concatenate((
        I, recon[None, ...], recon_no_second[None, ...]), axis=0)
    view(I0, montage_axis=0)
Beispiel #30
0
    plt.colorbar()
    plt.show()
    csm_mag = np.tile(np.abs(csm), (
        npcs,
        1,
        1,
        1,
    )).transpose((1, 0, 2, 3))

    # Do the sim over all coils
    I = np.zeros((ncoils, npcs, N, N), dtype='complex')
    for cc in range(ncoils):
        I[cc, ...] = ssfp(T1s,
                          T2s,
                          TR,
                          alpha,
                          df,
                          pcs,
                          PD,
                          phi_rf=-phi_rf[cc, ...])

        # DON'T DO THIS, STUPID!
        # # phase-cycle correction
        # Imag = np.abs(I[cc, ...])
        # Iphase = np.angle(I[cc, ...]) - np.tile(pcs/2, (N, N, 1)).T
        # I[cc, ...] = Imag*np.exp(1j*Iphase)

    I *= csm_mag
    # view(I.transpose((2, 3, 0, 1)))

    # Estimate the sensitivity maps from coil images
    recons = np.zeros((ncoils, N, N), dtype='complex')