コード例 #1
0
    def test_simulated_phantom_2d(self):

        # Create the target field map
        dim = 64
        min_df, max_df = -500, 500
        fx = np.linspace(min_df, max_df, dim)
        fy = np.zeros(dim)
        field_map, _ = np.meshgrid(fx, fy)
        # field_map = 100*np.random.normal(0,1,(dim,dim))
        # view(field_map)

        # Simulate phase-cycled bSSFP acquisitons
        # Seems to be better with higher flip angle!
        # For some reason worse with higher TR
        args = {
            'TR': 5e-3,
            'alpha': np.pi / 3,
            'dims': (dim, dim),
            'FOV': ((-1, 1), (-1, 1)),
            'radius': .75,
            'field_map': field_map
        }
        pc_vals = [0, np.pi / 2, np.pi, 3 * np.pi / 2]
        pcs = np.zeros((len(pc_vals), dim, dim), dtype='complex')
        for ii, pc in enumerate(pc_vals):
            pcs[ii, ...] = bssfp_2d_cylinder(**args, phase_cyc=pc)
        # view(pcs)

        # Estimate field map using GS to ESM
        gsfm = gs_field_map(
            *[x.squeeze() for x in np.split(pcs, len(pc_vals))],
            TR=args['TR'],
            gs_recon_opts={'second_pass': False})
        # TODO: Interestingly, the second pass solution fails... Why is this?

        # Now do sims for GRE for a sanity check
        TE1 = args['TR'] / 2
        TE2 = TE1 - args['TR'] / 2
        PD, T1s, T2s = cylinder_2d(dims=args['dims'],
                                   FOV=args['FOV'],
                                   radius=args['radius'])
        m1 = gre_sim(T1s,
                     T2s,
                     TR=args['TR'],
                     TE=TE1,
                     alpha=args['alpha'],
                     field_map=args['field_map'],
                     dphi=0,
                     M0=PD,
                     tol=1e-4)
        m2 = gre_sim(T1s,
                     T2s,
                     TR=args['TR'],
                     TE=TE2,
                     alpha=args['alpha'],
                     field_map=args['field_map'],
                     dphi=0,
                     M0=PD,
                     tol=1e-4)
        grefm = dual_echo_gre(m1, m2, TE1, TE2)

        # Phase wrap the real field map so we prove equivalence up to phase
        # unwrapping...
        dTE = np.abs(TE1 - TE2)
        field_map_pw = np.mod(field_map - 1 /
                              (2 * dTE), 1 / dTE) - 1 / (2 * dTE)

        # Make sure we're getting the same thing when wrapped
        idx = np.where(np.abs(grefm) > 0)
        self.assertTrue(np.allclose(grefm[idx], field_map_pw[idx]))

        idx = np.where(np.abs(gsfm) > 0)
        self.assertTrue(np.allclose(gsfm[idx], field_map_pw[idx]))

        # Just for fun, try phase unwrapping...
        mask = np.zeros(gsfm.shape).astype(bool)
        mask[idx] = True

        # scale between [-pi,pi], do unwrap, scale back up
        scale_fac = np.pi / np.max(np.abs(gsfm)) * np.sign(np.max(gsfm))
        val = unwrap_phase(mask * gsfm * scale_fac) / scale_fac

        # For some reason the edges are off by about pi, so let's clip it...
        val = val[:, 19:-19]
        field_map_clipped = field_map[:, 19:-19]
        idx = np.where(np.abs(val) > 0)
        self.assertTrue(np.allclose(field_map_clipped[idx], val[idx]))
コード例 #2
0
        for jj, pc in enumerate(pc_vals):
            bssfp_acqs[jj, ..., ii] = bssfp_acq(T1s,
                                                T2s,
                                                PD,
                                                tv_field_map[..., ii],
                                                alpha=bssfp_alpha,
                                                TR=bssfp_TR,
                                                phase_cyc=pc)
    # view(bssfp_acqs[0,...],movie_axis=-1)
    # view(np.concatenate((gre_acqs,bssfp_acqs[0,...])),movie_axis=-1)

    # Now get field maps
    recon_fm = np.zeros(tv_field_map.shape)
    for ii in trange(time_pts, leave=False, desc='GSFM'):
        recon_fm[..., ii] = gs_field_map(*[
            x.squeeze() for x in np.split(bssfp_acqs[..., ii], len(pc_vals))
        ],
                                         TR=bssfp_TR)
    # recon_fm[0,0,:] = 1 # ref pixel
    # view(recon_fm,movie_axis=-1)
    # view(np.stack((recon_fm[31,16,:],tv_field_map[31,16,:])))

    # Compare to just getting field map 4 times
    avg_field_map = np.zeros(tv_field_map.shape)
    for ii in trange(len(pc_vals), desc='AvgFM', leave=False):
        avg_field_map += np.random.normal(0, sigma, tv_field_map.shape)
        avg_field_map[idx, :] += hrf0
    avg_field_map /= len(pc_vals)

    if plots:
        plt.plot(hrf0, label='HDR')
        plt.plot(recon_fm[31, 16, :], label='Recon FM')
コード例 #3
0
        'TR': 5e-3,
        'alpha': np.pi / 3,
        'dims': (dim, dim),
        'FOV': ((-1, 1), (-1, 1)),
        'radius': .75,
        'field_map': field_map
    }
    pc_vals = [0, np.pi / 2, np.pi, 3 * np.pi / 2]
    pcs = np.zeros((len(pc_vals), dim, dim), dtype='complex')
    for ii, pc in enumerate(pc_vals):
        pcs[ii, ...] = bssfp_2d_cylinder(**args, phase_cyc=pc)
    view(pcs)

    # Estimate field map using GS to ESM
    gsfm = gs_field_map(*[x.squeeze() for x in np.split(
        pcs, len(pc_vals))], \
        TR=args['TR'], gs_recon_opts={'second_pass': False})
    # TODO: Interestingly, the second pass solution fails... Why is this?
    view(gsfm)

    # Now do sims for GRE for a sanity check
    TE1 = args['TR'] / 2
    TE2 = TE1 - args['TR'] / 2
    PD, T1s, T2s = cylinder_2d(dims=args['dims'],
                               FOV=args['FOV'],
                               radius=args['radius'])
    m1 = gre_sim(T1s,
                 T2s,
                 TR=args['TR'],
                 TE=TE1,
                 alpha=args['alpha'],