def run(self, image):
        "Correct for Nyquist ghosting due to field inhomogeneity."
        if not verify_scanner_image(self, image): return
	if not self.fmap_file:
	    self.log("No field map file provided, quitting")
	    return
        if not image.isepi:
            self.log("Can't apply inhomogeneity correction"\
                     " to non-epi sequences, quitting")
            return
	fMap = readImage(self.fmap_file)
        # grab the fieldmap, ignore the mask
        fMap = fMap.subImage(0)
	if fMap.shape[-3:] != image.shape[-3:]:
	    self.log("This field map's shape does not match"\
                     " the image shape, quitting")
	    return
	
	shift = (image.idim * image.T_pe/2/N.pi)
        
        #watch the sign
        pixel_pos = -shift*fMap[:] + N.outer(N.arange(fMap.jdim),
                                             N.ones(fMap.jdim))
        
        image[:].real = resample_phase_axis(abs(image[:]), pixel_pos)
        image[:].imag = 0.
    def run(self, image):
        # basic tasks here:
        # 1: data preparation
        # 2: phase unwrapping
        # 3: find mean phase diff lines (2 means or 4, depending on sequence)
        # 4: solve for linear coefficients
        # 5: create correction matrix from coefs
        # 6: apply correction to all image volumes
        #
        # * all linearly-sampled data can be treated in a generalized way by
        #   paying attention to the interleave factor (self.xleave) and
        #   the sampling trajectory+timing of each row (image.epi_trajectory)
        #
        # * centric sampled data, whose k-space trajectory had opposite
        #   directions, needs special treatment: basically the general case
        #   is handled in separated parts

        if not verify_scanner_image(self, image):
            return -1
        if not hasattr(image, "ref_data"):
            self.log("No reference volume, quitting")
            return -1
        if len(image.ref_data.shape) > 3 and image.ref_data.shape[-4] > 1:
            self.log("Could be performing Balanced Phase Correction!")

        self.volShape = image.shape[-3:]
        refVol = image.ref_data[0]
        n_slice, n_ref_rows, n_fe = self.refShape = refVol.shape
        # iscentric says whether kspace is multishot centric;
        # xleave is the factor to which kspace data has been interleaved
        # (in the case of multishot interleave)
        iscentric = image.sampstyle is "centric"
        self.xleave = iscentric and 1 or image.nseg
        self.alpha, self.beta, _, self.ref_alpha = image.epi_trajectory()
        # get slice positions (in order) so we can throw out the ones
        # too close to the backplane of the headcoil
        # self.good_slices = tag_backplane_slices(image)
        self.good_slices = range(n_slice)

        # want to fork the code based on sampling style
        if iscentric:
            theta = self.run_centric(image)
        else:
            theta = self.run_linear(image)

        phase = N.exp(-1.0j * theta).astype(image[:].dtype)
        from recon.tools import Recon

        ##         apply_phase_correction(image[:], phase)
        # this is faster??
        if Recon._FAST_ARRAY:
            apply_phase_correction(image[:], phase)
        else:
            for dvol in image:
                apply_phase_correction(dvol[:], phase)
示例#3
0
    def run(self, image):
        # basic tasks here:
        # 1: data preparation
        # 2: phase unwrapping
        # 3: find mean phase diff lines (2 means or 4, depending on sequence)
        # 4: solve for linear coefficients
        # 5: create correction matrix from coefs
        # 6: apply correction to all image volumes
        #
        # * all linearly-sampled data can be treated in a generalized way by
        #   paying attention to the interleave factor (self.xleave) and
        #   the sampling trajectory+timing of each row (image.epi_trajectory)
        #
        # * centric sampled data, whose k-space trajectory had opposite
        #   directions, needs special treatment: basically the general case
        #   is handled in separated parts

        if not verify_scanner_image(self, image):
            return -1
        if not hasattr(image, "ref_data"):
            self.log("No reference volume, quitting")
            return -1
        if len(image.ref_data.shape) > 3 and image.ref_data.shape[-4] > 1:
            self.log("Could be performing Balanced Phase Correction!")

        self.volShape = image.shape[-3:]
        refVol = image.ref_data[0]
        n_slice, n_ref_rows, n_fe = self.refShape = refVol.shape
        # iscentric says whether kspace is multishot centric;
        # xleave is the factor to which kspace data has been interleaved
        # (in the case of multishot interleave)
        iscentric = image.sampstyle is "centric"
        self.xleave = iscentric and 1 or image.nseg
        self.alpha, self.beta, _, self.ref_alpha = image.epi_trajectory()
        # get slice positions (in order) so we can throw out the ones
        # too close to the backplane of the headcoil
        #self.good_slices = tag_backplane_slices(image)
        self.good_slices = range(n_slice)

        # want to fork the code based on sampling style
        if iscentric:
            theta = self.run_centric(image)
        else:
            theta = self.run_linear(image)

        phase = N.exp(-1.j * theta).astype(image[:].dtype)
        from recon.tools import Recon
        ##         apply_phase_correction(image[:], phase)
        # this is faster??
        if Recon._FAST_ARRAY:
            apply_phase_correction(image[:], phase)
        else:
            for dvol in image:
                apply_phase_correction(dvol[:], phase)
示例#4
0
    def run(self, image):
        if not verify_scanner_image(self, image):
            return
        fmap_file = clean_name(self.fmap_file)[0]
        ##         if hasattr(image, 'n_chan'):
        ##             fmap_file += '.c%02d'%image.chan
        try:
            fmapIm = readImage(fmap_file)
        except:
            self.log("fieldmap not found: " + fmap_file)
            return -1
        (nslice, npe, nfe) = image.shape[-3:]
        # make sure that the length of the q1 columns of the fmap
        # are AT LEAST equal to that of the image
        regrid_fac = max(npe, fmapIm.shape[-2])
        # fmap and chi-mask are swapped to be of shape (Q1,Q2)
        fmap = np.swapaxes(
            regrid_bilinear(fmapIm[0], regrid_fac, axis=-2).astype(np.float64),
            -1, -2)
        chi = np.swapaxes(regrid_bilinear(fmapIm[1], regrid_fac, axis=-2), -1,
                          -2)
        Q1, Q2 = fmap.shape[-2:]

        # compute T_n2 vector
        Tl = image.T_pe
        delT = image.delT

        a, b, n2, _ = image.epi_trajectory()

        K = get_kernel(Q2, Tl, b, n2, fmap, chi)

        for s in range(nslice):
            # dchunk is shaped (nvol, npe, nfe)
            # inverse transform along nfe (can't do in-place)
            dchunk = ifft1(image[:, s, :, :])
            # now shape is (nfe, npe, nvol)
            dchunk = np.swapaxes(dchunk, 0, 2)
            for fe in range(nfe):
                # want to solve Kx = y for x
                # K is (npe,npe), and y is (npe,nvol)
                #
                # There seems to be a trade-off here as nvol changes...
                # Doing this in two steps is faster for large nvol; I think
                # it takes advantage of the faster BLAS matrix-product in dot
                # as opposed to LAPACK's linear solver. For smaller values
                # of nvol, the overhead seems to outweigh the benefit.
                iK = regularized_inverse(K[s, fe], self.lmbda)
                dchunk[fe] = np.dot(iK, dchunk[fe])
            dchunk = np.swapaxes(dchunk, 0, 2)
            # fft x back to kx, can do inplace here
            fft1(dchunk, inplace=True)
            image[:, s, :, :] = dchunk
    def run(self, image):
        if not verify_scanner_image(self, image):
            return
        fmap_file = clean_name(self.fmap_file)[0]
        ##         if hasattr(image, 'n_chan'):
        ##             fmap_file += '.c%02d'%image.chan
        try:
            fmapIm = readImage(fmap_file)
        except:
            self.log("fieldmap not found: " + fmap_file)
            return -1
        (nslice, npe, nfe) = image.shape[-3:]
        # make sure that the length of the q1 columns of the fmap
        # are AT LEAST equal to that of the image
        regrid_fac = max(npe, fmapIm.shape[-2])
        # fmap and chi-mask are swapped to be of shape (Q1,Q2)
        fmap = np.swapaxes(regrid_bilinear(fmapIm[0], regrid_fac, axis=-2).astype(np.float64), -1, -2)
        chi = np.swapaxes(regrid_bilinear(fmapIm[1], regrid_fac, axis=-2), -1, -2)
        Q1, Q2 = fmap.shape[-2:]

        # compute T_n2 vector
        Tl = image.T_pe
        delT = image.delT

        a, b, n2, _ = image.epi_trajectory()

        K = get_kernel(Q2, Tl, b, n2, fmap, chi)

        for s in range(nslice):
            # dchunk is shaped (nvol, npe, nfe)
            # inverse transform along nfe (can't do in-place)
            dchunk = ifft1(image[:, s, :, :])
            # now shape is (nfe, npe, nvol)
            dchunk = np.swapaxes(dchunk, 0, 2)
            for fe in range(nfe):
                # want to solve Kx = y for x
                # K is (npe,npe), and y is (npe,nvol)
                #
                # There seems to be a trade-off here as nvol changes...
                # Doing this in two steps is faster for large nvol; I think
                # it takes advantage of the faster BLAS matrix-product in dot
                # as opposed to LAPACK's linear solver. For smaller values
                # of nvol, the overhead seems to outweigh the benefit.
                iK = regularized_inverse(K[s, fe], self.lmbda)
                dchunk[fe] = np.dot(iK, dchunk[fe])
            dchunk = np.swapaxes(dchunk, 0, 2)
            # fft x back to kx, can do inplace here
            fft1(dchunk, inplace=True)
            image[:, s, :, :] = dchunk
示例#6
0
    def run(self, image):
        if not verify_scanner_image(self, image): return
        acq_order = image.acq_order
        data = image[:, :, :, :]
        change_slices_inplace(data, acq_order)

        if hasattr(image, 'ref_data'):
            data = image.ref_data[:, :, :, :]
            change_slices_inplace(data, acq_order)
        if hasattr(image, 'acs_data') and image.acs_data is not None:
            data = image.acs_data[:, :, :, :]
            change_slices_inplace(data, acq_order)
        if hasattr(image, 'acs_ref_data') and image.acs_ref_data is not None:
            data = image.acs_ref_data[:, :, :, :]
            change_slices_inplace(data, acq_order)
示例#7
0
 def run(self, image):
     if not verify_scanner_image(self, image): return
     acq_order = image.acq_order
     data = image[:,:,:,:]
     change_slices_inplace(data, acq_order)
     
     if hasattr(image, 'ref_data'):
         data = image.ref_data[:,:,:,:]
         change_slices_inplace(data, acq_order)
     if hasattr(image, 'acs_data') and image.acs_data is not None:
         data = image.acs_data[:,:,:,:]
         change_slices_inplace(data, acq_order)
     if hasattr(image, 'acs_ref_data') and image.acs_ref_data is not None:
         data = image.acs_ref_data[:,:,:,:]
         change_slices_inplace(data, acq_order)
示例#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)
    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)