def xformed_image_method(image, *args, **kwargs): print 'inverse transforming' util.ifft1(image.cdata, inplace=True, shift=True) util.ifft1(image.cacs_data, inplace=True, shift=True) fx = meth(image, *args, **kwargs) print 'forward transforming' util.fft1(image.cdata, inplace=True, shift=True) util.fft1(image.cacs_data, inplace=True, shift=True) if fx is not None: return fx
def run(self, image): arrays = (image.data, ) refs = (image.ref_data, ) samps = (image.n2_sampling, slice(None)) if hasattr(image, 'acs_data'): arrays += (image.acs_data, ) refs += (image.acs_ref_data, ) a, b = grappa_sampling(image.shape[-2], int(image.accel), image.n_acs) if len(b): init_acs_dir = (-1.0)**(a.tolist().index(b[0])) else: init_acs_dir = 1 polarities = (1.0, init_acs_dir) nr = image.n_ramp nf = image.n_flat if image.pslabel == 'ep2d_bold_acs_test' or image.accel > 2: acs_xleave = int(image.accel) else: acs_xleave = 1 xleaves = (1, int(acs_xleave)) for arr, n2, ref_arr, r, x in zip(arrays, samps, refs, polarities, xleaves): if arr is None: continue util.ifft1(arr, inplace=True, shift=True) # enforce 4D arrays arr.shape = (1, ) * (4 - len(arr.shape)) + arr.shape ref_arr.shape = (1, ) * (4 - len(ref_arr.shape)) + ref_arr.shape sub_samp_slicing = [slice(None)] * len(arr.shape) sub_samp_slicing[-2] = n2 Q2, Q1 = arr[sub_samp_slicing].shape[-2:] q1_ax = np.linspace(-Q1 / 2., Q1 / 2., Q1, endpoint=False) q2_pattern = r * np.power(-1.0, np.arange(Q2) / x) for v in xrange(arr.shape[0]): sub_samp_slicing[0] = v for sl in range(arr.shape[1]): sub_samp_slicing[1] = sl m = simple_unbal_phase_ramp(ref_arr[v, sl].copy(), nr, nf, image.pref_polarity, fov_lim=self.fov_lim, mask_noise=self.mask_noise) soln_pln = (m * q1_ax[None, :]) * q2_pattern[:, None] phs = np.exp(-1j * soln_pln) arr[sub_samp_slicing] *= phs # correct for flat dimensions arr.shape = tuple([d for d in arr.shape if d > 1]) util.fft1(arr, inplace=True, shift=True)
def run(self, image): arrays = (image.data,) refs = (image.ref_data,) samps = (image.n2_sampling, slice(None)) if hasattr(image, 'acs_data'): arrays += (image.acs_data,) refs += (image.acs_ref_data,) a,b = grappa_sampling(image.shape[-2], int(image.accel), image.n_acs) if len(b): init_acs_dir = (-1.0) ** (a.tolist().index(b[0])) else: init_acs_dir = 1 polarities = (1.0, init_acs_dir) nr = image.n_ramp nf = image.n_flat if image.pslabel == 'ep2d_bold_acs_test' or image.accel > 2: acs_xleave = int(image.accel) else: acs_xleave = 1 xleaves = (1, int(acs_xleave)) for arr, n2, ref_arr, r, x in zip(arrays, samps, refs, polarities, xleaves): if arr is None: continue util.ifft1(arr, inplace=True, shift=True) # enforce 4D arrays arr.shape = (1,)*(4-len(arr.shape)) + arr.shape ref_arr.shape = (1,)*(4-len(ref_arr.shape)) + ref_arr.shape sub_samp_slicing = [slice(None)]*len(arr.shape) sub_samp_slicing[-2] = n2 Q2, Q1 = arr[sub_samp_slicing].shape[-2:] q1_ax = np.linspace(-Q1/2., Q1/2., Q1, endpoint=False) q2_pattern = r*np.power(-1.0, np.arange(Q2)/x) for v in xrange(arr.shape[0]): sub_samp_slicing[0] = v for sl in range(arr.shape[1]): sub_samp_slicing[1] = sl m = simple_unbal_phase_ramp(ref_arr[v,sl].copy(), nr, nf, image.pref_polarity, fov_lim=self.fov_lim, mask_noise=self.mask_noise) soln_pln = (m * q1_ax[None,:]) * q2_pattern[:,None] phs = np.exp(-1j*soln_pln) arr[sub_samp_slicing] *= phs # correct for flat dimensions arr.shape = tuple([d for d in arr.shape if d > 1]) util.fft1(arr, inplace=True, shift=True)
def upsample(a, m): npts = a.shape[0]*m b = a.copy() # upsampe m times, stick the original ts in the middle of m samples a_up = np.zeros((npts,), a.dtype) a_up[m/2::m] = a util.fft1(a_up, inplace=True, shift=True) # LP filter to get sinc interpolation lpf = np.zeros((npts,)) bw = a.shape[0] lpf[npts/2-bw/2 : npts/2+bw/2] = 1. a_up *= lpf util.ifft1(a_up, inplace=True, shift=True) a_up *= float(m) return a_up
def simple_unbal_phase_ramp(rdata, nramp, nflat, pref_polarity, fov_lim=None, mask_noise=True, debug=False): N1 = rdata.shape[-1] rdata[:, :nramp + 1] = 0. rdata[:, nflat + 1:] = 0. irdata = util.ifft1(rdata, shift=True) if pref_polarity == 1: # [(pos - neg), (neg - pos)] ref_funcs = irdata[:2] * irdata[1:3].conj() else: # [(pos - neg), (neg - pos)] ref_funcs = irdata[:2].conj() * irdata[1:3] ref = ref_funcs[0] * ref_funcs[1].conjugate() ref_funcs_phs = np.angle(ref_funcs) pos_neg_diff = ref_funcs_phs[0] neg_pos_diff = ref_funcs_phs[1] ref_peak = np.abs(ref).max() # if an FOV limit is requested, then make sure the rest of the algorithm # only considers data within the limit if fov_lim: fov_max, fov = fov_lim dx = fov / N1 x_grid = np.arange(-N1 / 2, N1 / 2) * dx fov_q1_mask = np.where(np.abs(x_grid) > fov_max, 0, 1) else: fov_q1_mask = np.ones((N1, ), 'i') ref_peak = np.abs(ref * fov_q1_mask).max() if mask_noise: thresh = 0.1 nz_q1_mask = np.where(np.abs(ref) > thresh * ref_peak, 1, 0) while nz_q1_mask.sum() < 10: thresh *= 0.5 print 'relaxing threshold to include more points in the fit:', thresh nz_q1_mask = np.where(np.abs(ref) > thresh * ref_peak, 1, 0) else: nz_q1_mask = np.ones((N1, ), 'i') ref_phs = (pos_neg_diff - neg_pos_diff) q1_mask = nz_q1_mask & fov_q1_mask # only do the unwrapping in the method if noisy patches have been rejected m = util.find_ramp(ref_phs / 4., mask=q1_mask, do_unwrap=mask_noise, debug=debug) ## m,b,r = util.lin_regression(ref_phs/4, mask=nz_q1_mask & fov_q1_mask) ## m = m[0]; b = b[0] return m
def run(self, image): accel = int(image.accel) sub_data = image.cdata # shape (nc, nsl, n2, n1) acs = image.cacs_data # cheap fix for new shape of potentially multi-acquisition acs if len(acs.shape) > 4: acs = acs[:, 0, :, :, :] # transpose to (nsl, nc, n2, n1) acs = acs.transpose(1, 0, 2, 3).copy() if self.ft: print "transforming readout..." util.ifft1(sub_data, inplace=True, shift=True) util.ifft1(acs, inplace=True, shift=True) n2_sampling = image.pe_sampling[:] n2_sampling.sort() for s in range(image.n_slice): N, e = grappa_coefs(acs[s], accel, self.nblocks, sliding=self.sliding, n1_window=self.n1_window, loud=self.beloud, fixed_window=not self.floating_window) # find weightings for each slide reconstruction based on the # errors of their fits (slide enumeration in axis=-2) w = find_weights(e, axis=-2) if self.beloud: print e print w.sum(axis=-2) Ssub = sub_data[:, :, s, :, :] Ssub[:] = grappa_synthesize(Ssub, N, n2_sampling, weights=w, loud=self.beloud, fixed_window=not self.floating_window) if self.ft: util.fft1(sub_data, inplace=True, shift=True) util.fft1(acs, inplace=True, shift=True) # by convention, set view to channel 0 image.use_membuffer(0)
def simple_unbal_phase_ramp(rdata, nramp, nflat, pref_polarity, fov_lim=None, mask_noise=True, debug=False): N1 = rdata.shape[-1] rdata[:,:nramp+1] = 0. rdata[:,nflat+1:] = 0. irdata = util.ifft1(rdata, shift=True) if pref_polarity==1: # [(pos - neg), (neg - pos)] ref_funcs = irdata[:2] * irdata[1:3].conj() else: # [(pos - neg), (neg - pos)] ref_funcs = irdata[:2].conj()*irdata[1:3] ref = ref_funcs[0]*ref_funcs[1].conjugate() ref_funcs_phs = np.angle(ref_funcs) pos_neg_diff = ref_funcs_phs[0] neg_pos_diff = ref_funcs_phs[1] ref_peak = np.abs(ref).max() # if an FOV limit is requested, then make sure the rest of the algorithm # only considers data within the limit if fov_lim: fov_max, fov = fov_lim dx = fov/N1 x_grid = np.arange(-N1/2, N1/2) * dx fov_q1_mask = np.where(np.abs(x_grid)>fov_max,0,1) else: fov_q1_mask = np.ones((N1,), 'i') ref_peak = np.abs(ref*fov_q1_mask).max() if mask_noise: thresh = 0.1 nz_q1_mask = np.where(np.abs(ref) > thresh*ref_peak, 1, 0) while nz_q1_mask.sum() < 10: thresh *= 0.5 print 'relaxing threshold to include more points in the fit:', thresh nz_q1_mask = np.where(np.abs(ref) > thresh*ref_peak, 1, 0) else: nz_q1_mask = np.ones((N1,), 'i') ref_phs = (pos_neg_diff-neg_pos_diff) q1_mask = nz_q1_mask & fov_q1_mask # only do the unwrapping in the method if noisy patches have been rejected m = util.find_ramp(ref_phs/4., mask=q1_mask, do_unwrap=mask_noise, debug=debug) ## m,b,r = util.lin_regression(ref_phs/4, mask=nz_q1_mask & fov_q1_mask) ## m = m[0]; b = b[0] return m
def run(self, image): accel = int(image.accel) sub_data = image.cdata # shape (nc, nsl, n2, n1) acs = image.cacs_data # cheap fix for new shape of potentially multi-acquisition acs if len(acs.shape) > 4: acs = acs[:,0,:,:,:] # transpose to (nsl, nc, n2, n1) acs = acs.transpose(1, 0, 2, 3).copy() if self.ft: print "transforming readout..." util.ifft1(sub_data, inplace=True, shift=True) util.ifft1(acs, inplace=True, shift=True) n2_sampling = image.pe_sampling[:] n2_sampling.sort() for s in range(image.n_slice): N, e = grappa_coefs(acs[s], accel, self.nblocks, sliding=self.sliding, n1_window=self.n1_window, loud=self.beloud, fixed_window=not self.floating_window) # find weightings for each slide reconstruction based on the # errors of their fits (slide enumeration in axis=-2) w = find_weights(e, axis=-2) if self.beloud: print e print w.sum(axis=-2) Ssub = sub_data[:,:,s,:,:] Ssub[:] = grappa_synthesize(Ssub, N, n2_sampling, weights=w, loud=self.beloud, fixed_window=not self.floating_window) if self.ft: util.fft1(sub_data, inplace=True, shift=True) util.fft1(acs, inplace=True, shift=True) # by convention, set view to channel 0 image.use_membuffer(0)
def ksp_calib_hybrid_synth(image, Ny_blk, Nx_blk, sl=-1): R = int(image.accel) Nc = image.n_chan Nacs = int(image.n_acs) Nx = image.N1 Nv = image.n_vol Nfy = Nacs - (Ny_blk - 1) * R Nfx = Nx - (Nx_blk - 1) x_start = Nx_blk / 2 # lower inclusive limit for x target points x_end = x_start + Nfx - 1 # upper limit, inclusive, for x target points Npe = image.n_pe acs = image.cacs_data acs.shape = tuple([d for d in acs.shape if d > 1]) cdata = image.cdata # set up 2D neighborhood offsets xblk_offsets = np.arange(-(Nx_blk / 2), -(Nx_blk / 2) + Nx_blk) yblk_offsets = np.arange(-((Ny_blk - 1) / 2), -( (Ny_blk - 1) / 2) + Ny_blk) * R - 1 # fitting stage Ssrc = np.empty((Nfy * Nfx, Nc * Ny_blk * Nx_blk), 'F') Stgt = np.empty((Nfy * Nfx, (R - 1) * Nc), 'F') tgt_row0 = R * ((Ny_blk - 1) / 2) + 1 tgt_rows = np.arange(tgt_row0, tgt_row0 + Nfy) # transpose this array, since we will be indexing over x Wpad = np.zeros((Nx, Nc, Ny_blk, (R - 1) * Nc), 'F') Wpad_slice = [slice(None)] * len(Wpad.shape) kx0 = Nx / 2 + xblk_offsets[0] kx1 = Nx / 2 + xblk_offsets[-1] + 1 Wpad_slice[0] = slice(kx0, kx1) Wpad_slice = tuple(Wpad_slice) # synthesis stage pe_sampling = image.pe_sampling[:] pe_sampling.sort() acq_row0 = pe_sampling[0] # == 1 acq_rowf = pe_sampling[-1] + 1 # == last-sampled + 1 syn_rows = np.arange(tgt_row0 + 1, acq_rowf, R) Nu = len(syn_rows) # make Sacq with full readout points, and assume circularity in kx direction Sacq = np.empty((Nu * Nx * Nv, Nc * Ny_blk), 'F') Ssyn = np.empty((Nx, Nv * Nu, Nc * (R - 1)), 'F') sl_range = sl >= 0 and [sl] or xrange(image.n_slice) W_list = [] for s in sl_range: Dy_idx = tgt_rows[:, None] + yblk_offsets Stgt.shape = (Nfy, Nfx, (R - 1), Nc) print 'filling Stgt' inline(Stgt_fill, [ 'R', 'tgt_rows', 'Nfy', 'Nc', 'acs', 'Stgt', 'x_start', 'x_end', 's' ], type_converters=blitz) Stgt.shape = (Nfy * Nfx, (R - 1) * Nc) Ssrc.shape = (Nfy, Nfx, Nc, Ny_blk, Nx_blk) print 'filling Ssrc' inline(Ssrc_fill, [ 'Nc', 'Nfy', 'Nfx', 'Ny_blk', 'Nx_blk', 'Dy_idx', 'x_start', 'xblk_offsets', 'Ssrc', 'acs', 's' ], type_converters=blitz) Ssrc.shape = (Nfy * Nfx, Nc * Ny_blk * Nx_blk) W = np.linalg.lstsq(Ssrc, Stgt)[0] W.shape = (Nc, Ny_blk, Nx_blk, (R - 1) * Nc) W_list.append(W) util.ifft1(cdata, inplace=True, axis=-1) cdata *= Nx for W, s in zip(W_list, sl_range): # W indexes in rows as (chan, yn_idx, xn_idx) # W indexes in cols as (m, chan) Wpad[Wpad_slice] = W.transpose(2, 0, 1, 3) Wx = util.ifft1(Wpad, shift=True, inplace=False, axis=0) # Now each W(x) index in rows as (chan, yn_idx) # Now each W(x) index in cols as (m, chan) Wx.shape = (Nx, Nc * Ny_blk, (R - 1) * Nc) Wx *= Nx # want to repeatedly perform the linear combination of (Nc*Ny_blk) # points at all combinations of (Nu, Nx) # (Nu(x), Nc*Ny_blk) * W(x) Dy_idx = syn_rows[:, None] + yblk_offsets Sacq.shape = (Nx, Nv, Nu, Nc, Ny_blk) print 'filling acquisition rows, offsets', yblk_offsets inline( Sacq_fill, ['Nu', 'Nx', 'Nv', 'Nc', 'Ny_blk', 'Dy_idx', 'Sacq', 'cdata', 's'], type_converters=blitz) Sacq.shape = (Nx, Nv * Nu, Nc * Ny_blk) print 'synthesizing rows', syn_rows for xsyn, xacq, w in zip(Ssyn, Sacq, Wx): xsyn[:] = np.dot(xacq, w) Ssyn.shape = (Nx, Nv, Nu, R - 1, Nc) print 'filling synth rows' inline(Ssyn_fill, ['Nc', 'Nv', 'Nu', 'syn_rows', 'R', 'cdata', 'Ssyn', 's'], type_converters=blitz) util.fft1(cdata, inplace=True, axis=-1)
def ksp_calib_hybrid_synth(image, Ny_blk, Nx_blk, sl=-1): R = int(image.accel) Nc = image.n_chan Nacs = int(image.n_acs) Nx = image.N1 Nv = image.n_vol Nfy = Nacs - (Ny_blk-1)*R Nfx = Nx - (Nx_blk-1) x_start = Nx_blk/2 # lower inclusive limit for x target points x_end = x_start + Nfx - 1 # upper limit, inclusive, for x target points Npe = image.n_pe acs = image.cacs_data acs.shape = tuple([d for d in acs.shape if d > 1]) cdata = image.cdata # set up 2D neighborhood offsets xblk_offsets = np.arange(-(Nx_blk/2), -(Nx_blk/2)+Nx_blk) yblk_offsets = np.arange(-((Ny_blk-1)/2), -((Ny_blk-1)/2)+Ny_blk)*R - 1 # fitting stage Ssrc = np.empty((Nfy*Nfx, Nc*Ny_blk*Nx_blk), 'F') Stgt = np.empty((Nfy*Nfx, (R-1)*Nc), 'F') tgt_row0 = R * ((Ny_blk-1)/2) + 1 tgt_rows = np.arange(tgt_row0, tgt_row0 + Nfy) # transpose this array, since we will be indexing over x Wpad = np.zeros((Nx, Nc, Ny_blk, (R-1)*Nc), 'F') Wpad_slice = [slice(None)] * len(Wpad.shape) kx0 = Nx/2 + xblk_offsets[0] kx1 = Nx/2 + xblk_offsets[-1] + 1 Wpad_slice[0] = slice(kx0, kx1) Wpad_slice = tuple(Wpad_slice) # synthesis stage pe_sampling = image.pe_sampling[:] pe_sampling.sort() acq_row0 = pe_sampling[0] # == 1 acq_rowf = pe_sampling[-1]+1 # == last-sampled + 1 syn_rows = np.arange(tgt_row0+1, acq_rowf, R) Nu = len(syn_rows) # make Sacq with full readout points, and assume circularity in kx direction Sacq = np.empty((Nu*Nx*Nv, Nc*Ny_blk), 'F') Ssyn = np.empty((Nx, Nv*Nu, Nc*(R-1)), 'F') sl_range = sl>=0 and [sl] or xrange(image.n_slice) W_list = [] for s in sl_range: Dy_idx = tgt_rows[:,None] + yblk_offsets Stgt.shape = (Nfy, Nfx, (R-1), Nc) print 'filling Stgt' inline(Stgt_fill, ['R', 'tgt_rows', 'Nfy', 'Nc', 'acs', 'Stgt', 'x_start', 'x_end', 's'], type_converters=blitz) Stgt.shape = (Nfy*Nfx, (R-1)*Nc) Ssrc.shape = (Nfy, Nfx, Nc, Ny_blk, Nx_blk) print 'filling Ssrc' inline(Ssrc_fill, ['Nc', 'Nfy', 'Nfx', 'Ny_blk', 'Nx_blk', 'Dy_idx', 'x_start', 'xblk_offsets', 'Ssrc', 'acs', 's'], type_converters=blitz) Ssrc.shape = (Nfy*Nfx, Nc*Ny_blk*Nx_blk) W = np.linalg.lstsq(Ssrc, Stgt)[0] W.shape = (Nc, Ny_blk, Nx_blk, (R-1)*Nc) W_list.append(W) util.ifft1(cdata, inplace=True, axis=-1) cdata *= Nx for W, s in zip(W_list, sl_range): # W indexes in rows as (chan, yn_idx, xn_idx) # W indexes in cols as (m, chan) Wpad[Wpad_slice] = W.transpose(2, 0, 1, 3) Wx = util.ifft1(Wpad, shift=True, inplace=False, axis=0) # Now each W(x) index in rows as (chan, yn_idx) # Now each W(x) index in cols as (m, chan) Wx.shape = (Nx, Nc*Ny_blk, (R-1)*Nc) Wx *= Nx # want to repeatedly perform the linear combination of (Nc*Ny_blk) # points at all combinations of (Nu, Nx) # (Nu(x), Nc*Ny_blk) * W(x) Dy_idx = syn_rows[:,None] + yblk_offsets Sacq.shape = (Nx, Nv, Nu, Nc, Ny_blk) print 'filling acquisition rows, offsets', yblk_offsets inline(Sacq_fill, ['Nu', 'Nx', 'Nv', 'Nc', 'Ny_blk', 'Dy_idx', 'Sacq', 'cdata', 's'], type_converters=blitz) Sacq.shape = (Nx, Nv*Nu, Nc*Ny_blk) print 'synthesizing rows', syn_rows for xsyn, xacq, w in zip(Ssyn, Sacq, Wx): xsyn[:] = np.dot(xacq, w) Ssyn.shape = (Nx, Nv, Nu, R-1, Nc) print 'filling synth rows' inline(Ssyn_fill, ['Nc','Nv','Nu','syn_rows','R', 'cdata','Ssyn','s'], type_converters=blitz) util.fft1(cdata, inplace=True, axis=-1)