Ejemplo n.º 1
0
    def run(self, image):
        # can't perform segmentation correction on a non-segmented image!
        if image.nseg < 2:
            self.log("Image is non-segmented, nothing to do.")
            return
        pe_per_seg = image.n_pe_true/image.nseg

        # phase angle of inverse fft'd ref navs and image navs
        #ref_nav_phs = angle(ifft(image.ref_nav_data[0], shift=True))
        #nav_phs = angle(ifft(image.nav_data, shift=True))

        ref_nav_phs = N.angle(ifft(image.ref_nav_data[0]))
        nav_phs = N.angle(ifft(image.nav_data))

        # phase difference between ref navs and image navs
        phsdiff = normalize_angle(ref_nav_phs - nav_phs)

        # weight phase difference by the phase encode timing during each segment
        pe_times = (image.pe_times[image.nav_per_seg:]/image.echo_time)[:,N.newaxis]
        theta = N.empty(image.shape, N.float64)
        theta[:,:,:pe_per_seg] = phsdiff[:,:,N.newaxis,0]*pe_times
        theta[:,:,pe_per_seg:] = phsdiff[:,:,N.newaxis,1]*pe_times

        # Apply the phase correction.
        apply_phase_correction(image[:], N.exp(-1.j*theta))
    def run(self, image):
        # can't perform segmentation correction on a non-segmented image!
        if image.nseg < 2:
            self.log("Image is non-segmented, nothing to do.")
            return
        pe_per_seg = image.n_pe_true / image.nseg

        # phase angle of inverse fft'd ref navs and image navs
        #ref_nav_phs = angle(ifft(image.ref_nav_data[0], shift=True))
        #nav_phs = angle(ifft(image.nav_data, shift=True))

        ref_nav_phs = N.angle(ifft(image.ref_nav_data[0]))
        nav_phs = N.angle(ifft(image.nav_data))

        # phase difference between ref navs and image navs
        phsdiff = normalize_angle(ref_nav_phs - nav_phs)

        # weight phase difference by the phase encode timing during each segment
        pe_times = (image.pe_times[image.nav_per_seg:] /
                    image.echo_time)[:, N.newaxis]
        theta = N.empty(image.shape, N.float64)
        theta[:, :, :pe_per_seg] = phsdiff[:, :, N.newaxis, 0] * pe_times
        theta[:, :, pe_per_seg:] = phsdiff[:, :, N.newaxis, 1] * pe_times

        # Apply the phase correction.
        apply_phase_correction(image[:], N.exp(-1.j * theta))
Ejemplo n.º 3
0
    def run_linear(self, image):
        n_slice, n_ref_rows, n_fe = self.refShape

        N1 = image.shape[-1]
        n_conj_rows = n_ref_rows - self.xleave
        # form the S[u]S*[u+1] array:
        inv_ref = ifft(image.ref_data[0])
        inv_ref = inv_ref[:,:-self.xleave,:] * \
                  N.conjugate(inv_ref[:,self.xleave:,:])

        # Adjust the percentile parameter to reflect the percentage of
        # points that actually have data (not the pctage of all points).
        # Do this by determining the fraction of points that pass an
        # intensity threshold masking step.
        ir_mask = build_3Dmask(N.abs(inv_ref), 0.1)
        self.percentile *= ir_mask.sum() / (n_conj_rows * n_slice * n_fe)

        # partition the phase data based on acquisition order:
        # pos_order, neg_order define which rows in a slice are grouped
        # (remember not to count the lines contaminated by artifact!)
        pos_order = (self.ref_alpha[:n_conj_rows] > 0).nonzero()[0]
        neg_order = (self.ref_alpha[:n_conj_rows] < 0).nonzero()[0]

        # in Varian scans, the phase of the 0th product seems to be
        # contaminated.. so throw it out if there is at least one more
        # even-odd product
        # case < 3 ref rows: can't solve problem
        # case 3 ref rows: p0 from (0,1), n0 from (1,2)
        # case >=4 ref rows: p0 from (2,3), n0 from (1,2) (can kick line 0)
        # if the amount of data can support it, throw out p0
        if len(pos_order) > 1:
            pos_order = pos_order[1:]
        phs_vol = unwrap_ref_volume(inv_ref)
        phs_mean, q1_mask = mean_and_mask(phs_vol[:, pos_order, :],
                                          phs_vol[:, neg_order, :],
                                          self.percentile, self.good_slices)
        ### SOLVE FOR THE SYSTEM PARAMETERS
        if not self.shear_correct:
            if self.force_6p_soln:
                # solve for a1,a2,a3,a4,a5,a6, keep (a1,a3,a5)
                coefs = solve_phase_6d(phs_mean, q1_mask)
                coefs = coefs[0::2]
            else:
                coefs = solve_phase_3d(phs_mean, q1_mask)
            print coefs
            return correction_volume_3d(self.volShape, self.alpha, *coefs)
        else:
            coefs = solve_phase_6d(phs_mean, q1_mask)
            print coefs
            return correction_volume_6d(self.volShape, self.alpha, self.beta,
                                        *coefs)
Ejemplo n.º 4
0
    def run_linear(self, image):
        n_slice, n_ref_rows, n_fe = self.refShape

        N1 = image.shape[-1]
        n_conj_rows = n_ref_rows - self.xleave
        # form the S[u]S*[u+1] array:
        inv_ref = ifft(image.ref_data[0])
        inv_ref = inv_ref[:, : -self.xleave, :] * N.conjugate(inv_ref[:, self.xleave :, :])

        # Adjust the percentile parameter to reflect the percentage of
        # points that actually have data (not the pctage of all points).
        # Do this by determining the fraction of points that pass an
        # intensity threshold masking step.
        ir_mask = build_3Dmask(N.abs(inv_ref), 0.1)
        self.percentile *= ir_mask.sum() / (n_conj_rows * n_slice * n_fe)

        # partition the phase data based on acquisition order:
        # pos_order, neg_order define which rows in a slice are grouped
        # (remember not to count the lines contaminated by artifact!)
        pos_order = (self.ref_alpha[:n_conj_rows] > 0).nonzero()[0]
        neg_order = (self.ref_alpha[:n_conj_rows] < 0).nonzero()[0]

        # in Varian scans, the phase of the 0th product seems to be
        # contaminated.. so throw it out if there is at least one more
        # even-odd product
        # case < 3 ref rows: can't solve problem
        # case 3 ref rows: p0 from (0,1), n0 from (1,2)
        # case >=4 ref rows: p0 from (2,3), n0 from (1,2) (can kick line 0)
        # if the amount of data can support it, throw out p0
        if len(pos_order) > 1:
            pos_order = pos_order[1:]
        phs_vol = unwrap_ref_volume(inv_ref)
        phs_mean, q1_mask = mean_and_mask(
            phs_vol[:, pos_order, :], phs_vol[:, neg_order, :], self.percentile, self.good_slices
        )
        ### SOLVE FOR THE SYSTEM PARAMETERS
        if not self.shear_correct:
            if self.force_6p_soln:
                # solve for a1,a2,a3,a4,a5,a6, keep (a1,a3,a5)
                coefs = solve_phase_6d(phs_mean, q1_mask)
                coefs = coefs[0::2]
            else:
                coefs = solve_phase_3d(phs_mean, q1_mask)
            print coefs
            return correction_volume_3d(self.volShape, self.alpha, *coefs)
        else:
            coefs = solve_phase_6d(phs_mean, q1_mask)
            print coefs
            return correction_volume_6d(self.volShape, self.alpha, self.beta, *coefs)
Ejemplo n.º 5
0
    def run(self, image):
        if not hasattr(image, 'ref_data'):
            self.log("No reference data, nothing to do.")
            return
        if len(image.ref_vols) > 1:
            self.log("Could be performing Balanced Phase Correction!")

        # phase angle of inverse fft'd reference volume
        iref_data = ifft(image.ref_data[0])
        ref_phs = np.angle(iref_data)

        # apply correction to image data
        from recon.tools import Recon
        phase = np.exp(-1.j*ref_phs).astype(image[:].dtype)
        if Recon._FAST_ARRAY:
            apply_phase_correction(image[:], phase)
        else:
            for dvol in image:
                apply_phase_correction(dvol[:], phase)
Ejemplo n.º 6
0
    def run_centric(self, image):
        # centric sampling for epidw goes [0,..,31] then [-1,..,-32]
        # in index terms this is [32,33,..,63] + [31,30,..,0]

        # solving for angle(S[u]S*[u+1]) is equal to the basic problem for u>=0
        # for u<0:
        # angle(S[u]S*[u+1]) =   2[sign-flip-terms]*(-1)^(u+1) + [shear-terms]
        #                    = -(2[sign-flip-terms]*(-1)^u     - [shear-terms])
        # so by flipping the sign on the phs means data, we can solve for the
        # sign-flipping (raster) terms and the DC offset terms with the same
        # equations.

        n_slice, n_ref_rows, n_fe = self.refShape
        n_vol_rows = self.volShape[-2]
        n_conj_rows = n_ref_rows - 2
        # this is S[u]S*[u+1].. now with n_ref_rows-1 rows
        inv_ref = ifft(image.ref_data[0])
        inv_ref = inv_ref[:, :-1, :] * N.conjugate(inv_ref[:, 1:, :])

        # Adjust the percentile parameter to reflect the percentage of
        # points that actually have data (not the pctage of all points).
        # Do this by determining the fraction of points that pass an
        # intensity threshold masking step.
        ir_mask = build_3Dmask(N.abs(inv_ref), 0.1)
        self.percentile *= ir_mask.sum() / (n_conj_rows * (n_slice * n_fe))

        # in the lower segment, do NOT grab the n_ref_rows/2-th line..
        # its product spans the two segments
        cnj_upper = inv_ref[:, n_ref_rows / 2:, :].copy()
        cnj_lower = inv_ref[:, :n_ref_rows / 2 - 1, :].copy()

        phs_evn_upper = unwrap_ref_volume(cnj_upper[:, 0::2, :])
        phs_odd_upper = unwrap_ref_volume(cnj_upper[:, 1::2, :])
        # 0th phase diff on the upper trajectory is contaminated by eddy curr,
        # throw it out if possible:
        if phs_evn_upper.shape[-2] > 1:
            phs_evn_upper = phs_evn_upper[:, 1:, :]
        phs_evn_lower = unwrap_ref_volume(cnj_lower[:, 0::2, :])
        phs_odd_lower = unwrap_ref_volume(cnj_lower[:, 1::2, :])
        # 0th phase diff on downward trajectory (== S[u]S*[u+1] for u=-30)
        # is contaminated too
        if phs_evn_lower.shape[-2] > 1:
            phs_evn_lower = phs_evn_lower[:, :-1, :]

        phs_mean_upper, q1_mask_upper = \
                        mean_and_mask(phs_evn_upper, phs_odd_upper,
                                      self.percentile, self.good_slices)
        phs_mean_lower, q1_mask_lower = \
                        mean_and_mask(phs_evn_lower, phs_odd_lower,
                                      self.percentile, self.good_slices)
        if not self.shear_correct:
            # for upper (u>=0), solve normal SVD
            if self.force_6p_soln:
                coefs = solve_phase_6d(phs_mean_upper, q1_mask_upper)
                coefs = coefs[0::2]
            else:
                coefs = solve_phase_3d(phs_mean_upper, q1_mask_upper)
            print coefs
            theta_upper = correction_volume_3d(self.volShape, self.alpha,
                                               *coefs)
            # for lower (u < 0), solve with negative data
            if self.force_6p_soln:
                coefs = solve_phase_6d(-phs_mean_lower, q1_mask_lower)
                coefs = coefs[0::2]
            else:
                coefs = solve_phase_3d(-phs_mean_lower, q1_mask_lower)
            print coefs
            theta_lower = correction_volume_3d(self.volShape, self.alpha,
                                               *coefs)
            theta_lower[:,
                        n_vol_rows / 2:, :] = theta_upper[:,
                                                          n_vol_rows / 2:, :]
            return theta_lower
        else:
            # for upper (u>=0), solve normal SVD
            coefs = solve_phase_6d(phs_mean_upper, q1_mask_upper)
            print coefs
            theta_upper = correction_volume_6d(self.volShape, self.alpha,
                                               self.beta, *coefs)
            # for lower (u < 0), solve with negative data
            coefs = solve_phase_6d(-phs_mean_lower, q1_mask_lower)
            print coefs
            theta_lower = correction_volume_6d(self.volShape, self.alpha,
                                               self.beta, *coefs)
            theta_lower[:,
                        n_vol_rows / 2:, :] = theta_upper[:,
                                                          n_vol_rows / 2:, :]
            return theta_lower
Ejemplo n.º 7
0
    def run_centric(self, image):
        # centric sampling for epidw goes [0,..,31] then [-1,..,-32]
        # in index terms this is [32,33,..,63] + [31,30,..,0]

        # solving for angle(S[u]S*[u+1]) is equal to the basic problem for u>=0
        # for u<0:
        # angle(S[u]S*[u+1]) =   2[sign-flip-terms]*(-1)^(u+1) + [shear-terms]
        #                    = -(2[sign-flip-terms]*(-1)^u     - [shear-terms])
        # so by flipping the sign on the phs means data, we can solve for the
        # sign-flipping (raster) terms and the DC offset terms with the same
        # equations.

        n_slice, n_ref_rows, n_fe = self.refShape
        n_vol_rows = self.volShape[-2]
        n_conj_rows = n_ref_rows - 2
        # this is S[u]S*[u+1].. now with n_ref_rows-1 rows
        inv_ref = ifft(image.ref_data[0])
        inv_ref = inv_ref[:, :-1, :] * N.conjugate(inv_ref[:, 1:, :])

        # Adjust the percentile parameter to reflect the percentage of
        # points that actually have data (not the pctage of all points).
        # Do this by determining the fraction of points that pass an
        # intensity threshold masking step.
        ir_mask = build_3Dmask(N.abs(inv_ref), 0.1)
        self.percentile *= ir_mask.sum() / (n_conj_rows * (n_slice * n_fe))

        # in the lower segment, do NOT grab the n_ref_rows/2-th line..
        # its product spans the two segments
        cnj_upper = inv_ref[:, n_ref_rows / 2 :, :].copy()
        cnj_lower = inv_ref[:, : n_ref_rows / 2 - 1, :].copy()

        phs_evn_upper = unwrap_ref_volume(cnj_upper[:, 0::2, :])
        phs_odd_upper = unwrap_ref_volume(cnj_upper[:, 1::2, :])
        # 0th phase diff on the upper trajectory is contaminated by eddy curr,
        # throw it out if possible:
        if phs_evn_upper.shape[-2] > 1:
            phs_evn_upper = phs_evn_upper[:, 1:, :]
        phs_evn_lower = unwrap_ref_volume(cnj_lower[:, 0::2, :])
        phs_odd_lower = unwrap_ref_volume(cnj_lower[:, 1::2, :])
        # 0th phase diff on downward trajectory (== S[u]S*[u+1] for u=-30)
        # is contaminated too
        if phs_evn_lower.shape[-2] > 1:
            phs_evn_lower = phs_evn_lower[:, :-1, :]

        phs_mean_upper, q1_mask_upper = mean_and_mask(phs_evn_upper, phs_odd_upper, self.percentile, self.good_slices)
        phs_mean_lower, q1_mask_lower = mean_and_mask(phs_evn_lower, phs_odd_lower, self.percentile, self.good_slices)
        if not self.shear_correct:
            # for upper (u>=0), solve normal SVD
            if self.force_6p_soln:
                coefs = solve_phase_6d(phs_mean_upper, q1_mask_upper)
                coefs = coefs[0::2]
            else:
                coefs = solve_phase_3d(phs_mean_upper, q1_mask_upper)
            print coefs
            theta_upper = correction_volume_3d(self.volShape, self.alpha, *coefs)
            # for lower (u < 0), solve with negative data
            if self.force_6p_soln:
                coefs = solve_phase_6d(-phs_mean_lower, q1_mask_lower)
                coefs = coefs[0::2]
            else:
                coefs = solve_phase_3d(-phs_mean_lower, q1_mask_lower)
            print coefs
            theta_lower = correction_volume_3d(self.volShape, self.alpha, *coefs)
            theta_lower[:, n_vol_rows / 2 :, :] = theta_upper[:, n_vol_rows / 2 :, :]
            return theta_lower
        else:
            # for upper (u>=0), solve normal SVD
            coefs = solve_phase_6d(phs_mean_upper, q1_mask_upper)
            print coefs
            theta_upper = correction_volume_6d(self.volShape, self.alpha, self.beta, *coefs)
            # for lower (u < 0), solve with negative data
            coefs = solve_phase_6d(-phs_mean_lower, q1_mask_lower)
            print coefs
            theta_lower = correction_volume_6d(self.volShape, self.alpha, self.beta, *coefs)
            theta_lower[:, n_vol_rows / 2 :, :] = theta_upper[:, n_vol_rows / 2 :, :]
            return theta_lower
Ejemplo n.º 8
0
    def run(self, image):

        if not verify_scanner_image(self, image):
            return -1

        if not hasattr(image, "ref_data") or image.ref_data.shape[0] < 2:
            self.log("Not enough reference volumes, quitting.")
            return -1

        self.volShape = image.shape[-3:]
        inv_ref0 = ifft(image.ref_data[0])
        inv_ref1 = ifft(reverse(image.ref_data[1], axis=-1))

        inv_ref = inv_ref0 * N.conjugate(inv_ref1)

        n_slice, n_pe, n_fe = self.refShape = inv_ref0.shape

        #phs_vol comes back shaped (n_slice, n_pe, lin2-lin1)
        phs_vol = unwrap_ref_volume(inv_ref)

        q1_mask = N.zeros((n_slice, n_pe, n_fe))

        # get slice positions (in order) so we can throw out the ones
        # too close to the backplane of the headcoil (or not ???)
        if self.backplane_adj:
            s_idx = tag_backplane_slices(image)
        else:
            s_idx = range(n_slice)
        q1_mask[s_idx] = 1.0
        q1_mask[s_idx, 0::2, :] = qual_map_mask(phs_vol[s_idx, 0::2, :],
                                                self.percentile)
        q1_mask[s_idx, 1::2, :] = qual_map_mask(phs_vol[s_idx, 1::2, :],
                                                self.percentile)
        theta = N.empty(self.refShape, N.float64)
        s_line = N.arange(n_slice)
        r_line = N.arange(n_fe) - n_fe / 2

        B1, B2, B3 = range(3)

        # planar solution
        nrows = n_slice * n_fe
        M = N.zeros((nrows, 3), N.float64)
        M[:, B1] = N.outer(N.ones(n_slice), r_line).flatten()
        M[:, B2] = N.repeat(s_line, n_fe)
        M[:, B3] = 1.

        A = N.empty((n_slice, 3), N.float64)
        B = N.empty((3, n_fe), N.float64)
        A[:, 0] = 1.
        A[:, 1] = s_line
        A[:, 2] = 1.
        if not self.fitmeans:
            for m in range(n_pe):
                P = N.reshape(0.5 * phs_vol[:, m, :], (nrows, ))
                pt_mask = N.reshape(q1_mask[:, m, :], (nrows, ))
                nz = pt_mask.nonzero()[0]
                Msub = M[nz]
                P = P[nz]
                [u, sv, vt] = N.linalg.svd(Msub, full_matrices=0)
                coefs = N.dot(vt.transpose(),
                              N.dot(N.diag(1 / sv), N.dot(u.transpose(), P)))

                B[0, :] = coefs[B1] * r_line
                B[1, :] = coefs[B2]
                B[2, :] = coefs[B3]
                theta[:, m, :] = N.dot(A, B)
        else:
            for rows in ('evn', 'odd'):
                if rows is 'evn':
                    slicing = (slice(None), slice(0, n_pe, 2), slice(None))
                else:
                    slicing = (slice(None), slice(1, n_pe, 2), slice(None))
                P = N.reshape(0.5 * phs_vol[slicing].mean(axis=-2), (nrows, ))
                pt_mask = q1_mask[slicing].prod(axis=-2)
                pt_mask.shape = (nrows, )
                nz = pt_mask.nonzero()[0]
                Msub = M[nz]
                P = P[nz]
                [u, sv, vt] = N.linalg.svd(Msub, full_matrices=0)
                coefs = N.dot(vt.transpose(),
                              N.dot(N.diag(1 / sv), N.dot(u.transpose(), P)))
                B[0, :] = coefs[B1] * r_line
                B[1, :] = coefs[B2]
                B[2, :] = coefs[B3]
                theta[slicing] = N.dot(A, B)[:, None, :]

        phase = N.exp(-1.j * theta).astype(image[:].dtype)
        from recon.tools import Recon
        if Recon._FAST_ARRAY:
            apply_phase_correction(image[:], phase)
        else:
            for dvol in image:
                apply_phase_correction(dvol[:], phase)
Ejemplo n.º 9
0
    def run(self, image):
        
        if not verify_scanner_image(self, image):
            return -1
        
        if not hasattr(image, "ref_data") or image.ref_data.shape[0] < 2:
            self.log("Not enough reference volumes, quitting.")
            return -1

        self.volShape = image.shape[-3:]
        inv_ref0 = ifft(image.ref_data[0])
        inv_ref1 = ifft(reverse(image.ref_data[1], axis=-1))

        inv_ref = inv_ref0*N.conjugate(inv_ref1)
        
        n_slice, n_pe, n_fe = self.refShape = inv_ref0.shape

        #phs_vol comes back shaped (n_slice, n_pe, lin2-lin1)
        phs_vol = unwrap_ref_volume(inv_ref)
        
        q1_mask = N.zeros((n_slice, n_pe, n_fe))

        # get slice positions (in order) so we can throw out the ones
        # too close to the backplane of the headcoil (or not ???)
        if self.backplane_adj:
            s_idx = tag_backplane_slices(image)
        else:
            s_idx = range(n_slice)
        q1_mask[s_idx] = 1.0
        q1_mask[s_idx,0::2,:] =  qual_map_mask(phs_vol[s_idx,0::2,:],
                                              self.percentile)
        q1_mask[s_idx,1::2,:] = qual_map_mask(phs_vol[s_idx,1::2,:],
                                              self.percentile)
        theta = N.empty(self.refShape, N.float64)
        s_line = N.arange(n_slice)
        r_line = N.arange(n_fe) - n_fe/2

        B1, B2, B3 = range(3)

        # planar solution
        nrows = n_slice * n_fe
        M = N.zeros((nrows, 3), N.float64)
        M[:,B1] = N.outer(N.ones(n_slice), r_line).flatten()
        M[:,B2] = N.repeat(s_line, n_fe)
        M[:,B3] = 1.
        
        A = N.empty((n_slice, 3), N.float64)
        B = N.empty((3, n_fe), N.float64)
        A[:,0] = 1.
        A[:,1] = s_line
        A[:,2] = 1.
        if not self.fitmeans:
            for m in range(n_pe):
                P = N.reshape(0.5*phs_vol[:,m,:], (nrows,))
                pt_mask = N.reshape(q1_mask[:,m,:], (nrows,))
                nz = pt_mask.nonzero()[0]
                Msub = M[nz]
                P = P[nz]
                [u,sv,vt] = N.linalg.svd(Msub, full_matrices=0)
                coefs = N.dot(vt.transpose(),
                              N.dot(N.diag(1/sv), N.dot(u.transpose(), P)))
                
                B[0,:] = coefs[B1]*r_line
                B[1,:] = coefs[B2]
                B[2,:] = coefs[B3]
                theta[:,m,:] = N.dot(A,B)
        else:
            for rows in ( 'evn', 'odd' ):
                if rows is 'evn':
                    slicing = ( slice(None), slice(0, n_pe, 2), slice(None) )
                else:
                    slicing = ( slice(None), slice(1, n_pe, 2), slice(None) )
                P = N.reshape(0.5*phs_vol[slicing].mean(axis=-2), (nrows,))
                pt_mask = q1_mask[slicing].prod(axis=-2)
                pt_mask.shape = (nrows,)
                nz = pt_mask.nonzero()[0]
                Msub = M[nz]
                P = P[nz]
                [u,sv,vt] = N.linalg.svd(Msub, full_matrices=0)
                coefs = N.dot(vt.transpose(),
                              N.dot(N.diag(1/sv), N.dot(u.transpose(), P)))
                B[0,:] = coefs[B1]*r_line
                B[1,:] = coefs[B2]
                B[2,:] = coefs[B3]
                theta[slicing] = N.dot(A,B)[:,None,:]

            
        phase = N.exp(-1.j*theta).astype(image[:].dtype)
        from recon.tools import Recon
        if Recon._FAST_ARRAY:
            apply_phase_correction(image[:], phase)
        else:
            for dvol in image:
                apply_phase_correction(dvol[:], phase)