def __init__(self, image=None): if image is None: image = ReconImage(np.ones((4,4,4)), 1, 1, 1, 1) if not isinstance(image, ReconImage): image = ReconImage(np.asarray(image), 1, 1, 1, 1) for (attr, val) in image.__dict__.items(): self.__dict__[attr] = val # get vox origin from zyx origin (can't use transform because # (these zyx are in the image's native space) self.r0 = np.array([self.z0, self.y0, self.x0]) self.dr = np.array([self.ksize, self.jsize, self.isize]) # orientation xform maps vx-space:xyz-space (Right,Anterior,Superior) # numpy arrays are in C-ordering (zyx), so I'm going to reverse the # rows and columns of the xform to be in zyx order M = self.orientation_xform.tomatrix() self.xform = reverse(reverse(M, axis=-1), axis=-2) self.pxform = nearest_simple_transform(M) self.pxform = reverse(reverse(self.pxform,axis=-1),axis=-2) if not np.allclose(self.xform, self.pxform): print 'OBLIQUE IMAGE: NEED TO PLOT IN ROTATED "VOXEL" SPACE' sl0_vox_center = np.array([0, self.jdim/2, self.idim/2]) sl0_center = np.dot(self.xform*self.dr, sl0_vox_center) + self.r0 # reset this r0 to correspond to the rotated voxel box self.r0 = sl0_center - np.dot(self.pxform*self.dr, sl0_vox_center) # reset the xform to be the planar xform self.xform = self.pxform print self.r0 # These variables describe which dimension a given standard slicing # (axial, sagittal, coronal) slices in the data array self.ax, self.cor, self.sag = abs(np.dot(self.pxform, np.arange(3)).astype(np.int32)).tolist() self.prefilter = None self.vox_coords = self.zyx2vox([0,0,0])
def data_xform(self, slice_idx, zyx_coords): """Given the a sliceplots slicing index and the current vox position, get a slice of data. """ slicer = [slice(0,d) for d in self.shape] slicer[slice_idx] = self.zyx2vox(zyx_coords)[slice_idx] slicer = tuple(slicer) Msub = self.plane_xform(slice_idx) Msub = reverse(reverse(Msub, axis=-1), axis=-2) xform = compose_xform(Msub) return xform(self[slicer])
def circularize(a): To = a.shape[-1] T = 3 * To - 2 + To % 2 buf_dtype = np.dtype(a.dtype.char.upper()) ts_buf = np.empty(a.shape[:-1] + (T, ), buf_dtype) ## point-sharing, no negation or shift ## if a = [2, 3, 4, 5, 6], then ts_buf will be: ## [6, 5, 4, 3, (2, 3, 4, 5, 6,) 5, 4, 3, 2, ((2))] ts_buf[..., To - 1:2 * To - 1] = a # imaginary part of ts is odd.. ts[-t] = -ts[t] ts_buf[..., :To - 1] = np.conj(reverse(a[..., 1:])) #ts_buf[...,:To-1] = reverse(a[...,1:]) ts_buf[..., 2 * To - 1:3 * To - 2] = reverse(a[..., :To - 1]) if To % 2: ts_buf[..., -1] = ts_buf[..., -2] return ts_buf
def subsampInterp_regular(ts, c, axis=-1): """Makes a subsample sinc interpolation on an N-D array in a given axis. This uses sinc interpolation to return ts(t-a), where a is related to the factor c as described below. ts : the N-D array with a time series in "axis" c : the fraction of the sampling interval such that a = c*dt -- note that c is only useful in the interval (0, 1] axis : specifies the axis of the time dimension """ To = ts.shape[axis] # put time series in the last dimension if axis != -1: ts = np.swapaxes(ts, axis, -1) ## ts_buf = circularize(ts) ts_buf = ts.copy() T = ts_buf.shape[-1] Fn = T / 2 + 1 # make sure the interpolating filter's dtype is complex! filter_dtype = np.dtype(ts.dtype.char.upper()) phs_shift = np.empty((T,), filter_dtype) phs_shift[:Fn] = np.exp(-2.0j * np.pi * c * np.arange(Fn) / float(T)) phs_shift[Fn:] = np.conjugate(reverse(phs_shift[1 : T - (Fn - 1)])) fft(ts_buf, shift=False, inplace=True) np.multiply(ts_buf, phs_shift, ts_buf) ifft(ts_buf, shift=False, inplace=True) ## ts[:] = ts_buf[...,To-1:2*To-1] ts[:] = ts_buf[:] del ts_buf if axis != -1: ts = np.swapaxes(ts, axis, -1)
def circularize(a): To = a.shape[-1] T = 3 * To - 2 + To % 2 buf_dtype = np.dtype(a.dtype.char.upper()) ts_buf = np.empty(a.shape[:-1] + (T,), buf_dtype) ## point-sharing, no negation or shift ## if a = [2, 3, 4, 5, 6], then ts_buf will be: ## [6, 5, 4, 3, (2, 3, 4, 5, 6,) 5, 4, 3, 2, ((2))] ts_buf[..., To - 1 : 2 * To - 1] = a # imaginary part of ts is odd.. ts[-t] = -ts[t] ts_buf[..., : To - 1] = np.conj(reverse(a[..., 1:])) # ts_buf[...,:To-1] = reverse(a[...,1:]) ts_buf[..., 2 * To - 1 : 3 * To - 2] = reverse(a[..., : To - 1]) if To % 2: ts_buf[..., -1] = ts_buf[..., -2] return ts_buf
def subsampInterp_regular(ts, c, axis=-1): """Makes a subsample sinc interpolation on an N-D array in a given axis. This uses sinc interpolation to return ts(t-a), where a is related to the factor c as described below. ts : the N-D array with a time series in "axis" c : the fraction of the sampling interval such that a = c*dt -- note that c is only useful in the interval (0, 1] axis : specifies the axis of the time dimension """ To = ts.shape[axis] # put time series in the last dimension if axis != -1: ts = np.swapaxes(ts, axis, -1) ## ts_buf = circularize(ts) ts_buf = ts.copy() T = ts_buf.shape[-1] Fn = T / 2 + 1 # make sure the interpolating filter's dtype is complex! filter_dtype = np.dtype(ts.dtype.char.upper()) phs_shift = np.empty((T, ), filter_dtype) phs_shift[:Fn] = np.exp(-2.j * np.pi * c * np.arange(Fn) / float(T)) phs_shift[Fn:] = np.conjugate(reverse(phs_shift[1:T - (Fn - 1)])) fft(ts_buf, shift=False, inplace=True) np.multiply(ts_buf, phs_shift, ts_buf) ifft(ts_buf, shift=False, inplace=True) ## ts[:] = ts_buf[...,To-1:2*To-1] ts[:] = ts_buf[:] del ts_buf if axis != -1: ts = np.swapaxes(ts, axis, -1)
def subsampInterp(ts, c, axis=-1): """Makes a subsample sinc interpolation on an N-D array in a given axis. This uses sinc interpolation to return ts(t-a), where a is related to the factor c as described below. ts : the N-D array with a time series in "axis" c : the fraction of the sampling interval such that a = c*dt -- note that c is only useful in the interval (0, 1] axis : specifies the axis of the time dimension """ To = ts.shape[axis] # find ramps and subtract them ramps = np.empty_like(ts) rax_shape = [1] * len(ts.shape) rax_shape[axis] = To rax = np.arange(To) rax.shape = rax_shape (mre, b, r) = lin_regression(ts.real, axis=axis) ramps.real[:] = rax * mre if ts.dtype.type in np.sctypes["complex"]: (mim, b, r) = lin_regression(ts.imag, axis=axis) ramps.imag[:] = rax * mim np.subtract(ts, ramps, ts) # find biases and subtract them ts_mean = ts.mean(axis=axis) if len(ts_mean.shape): mean_shape = list(ts.shape) mean_shape[axis] = 1 ts_mean.shape = tuple(mean_shape) np.subtract(ts, ts_mean, ts) # put time series in the last dimension if axis != -1: ts = np.swapaxes(ts, axis, -1) ts_buf = circularize(ts) ## ts_buf = ts.copy() T = ts_buf.shape[-1] Fn = T / 2 + 1 # make sure the interpolating filter's dtype is complex! filter_dtype = np.dtype(ts.dtype.char.upper()) phs_shift = np.empty((T,), filter_dtype) phs_shift[:Fn] = np.exp(-2.0j * np.pi * c * np.arange(Fn) / float(T)) phs_shift[Fn:] = np.conjugate(reverse(phs_shift[1 : T - (Fn - 1)])) fft(ts_buf, shift=False, inplace=True) np.multiply(ts_buf, phs_shift, ts_buf) ifft(ts_buf, shift=False, inplace=True) ts[:] = ts_buf[..., To - 1 : 2 * To - 1] ## ts[:] = ts_buf[:] del ts_buf if axis != -1: ts = np.swapaxes(ts, axis, -1) # add back biases and analytically interpolated ramps np.subtract(rax, c, rax) # np.add(rax, c, rax) ramps.real[:] = rax * mre if ts.dtype.type in np.sctypes["complex"]: ramps.imag[:] = rax * mim np.add(ts, ramps, ts) np.add(ts, ts_mean, ts)
def subsampInterp(ts, c, axis=-1): """Makes a subsample sinc interpolation on an N-D array in a given axis. This uses sinc interpolation to return ts(t-a), where a is related to the factor c as described below. ts : the N-D array with a time series in "axis" c : the fraction of the sampling interval such that a = c*dt -- note that c is only useful in the interval (0, 1] axis : specifies the axis of the time dimension """ To = ts.shape[axis] # find ramps and subtract them ramps = np.empty_like(ts) rax_shape = [1] * len(ts.shape) rax_shape[axis] = To rax = np.arange(To) rax.shape = rax_shape (mre, b, r) = lin_regression(ts.real, axis=axis) ramps.real[:] = rax * mre if ts.dtype.type in np.sctypes['complex']: (mim, b, r) = lin_regression(ts.imag, axis=axis) ramps.imag[:] = (rax * mim) np.subtract(ts, ramps, ts) # find biases and subtract them ts_mean = ts.mean(axis=axis) if len(ts_mean.shape): mean_shape = list(ts.shape) mean_shape[axis] = 1 ts_mean.shape = tuple(mean_shape) np.subtract(ts, ts_mean, ts) # put time series in the last dimension if axis != -1: ts = np.swapaxes(ts, axis, -1) ts_buf = circularize(ts) ## ts_buf = ts.copy() T = ts_buf.shape[-1] Fn = T / 2 + 1 # make sure the interpolating filter's dtype is complex! filter_dtype = np.dtype(ts.dtype.char.upper()) phs_shift = np.empty((T, ), filter_dtype) phs_shift[:Fn] = np.exp(-2.j * np.pi * c * np.arange(Fn) / float(T)) phs_shift[Fn:] = np.conjugate(reverse(phs_shift[1:T - (Fn - 1)])) fft(ts_buf, shift=False, inplace=True) np.multiply(ts_buf, phs_shift, ts_buf) ifft(ts_buf, shift=False, inplace=True) ts[:] = ts_buf[..., To - 1:2 * To - 1] ## ts[:] = ts_buf[:] del ts_buf if axis != -1: ts = np.swapaxes(ts, axis, -1) # add back biases and analytically interpolated ramps np.subtract(rax, c, rax) #np.add(rax, c, rax) ramps.real[:] = rax * mre if ts.dtype.type in np.sctypes['complex']: ramps.imag[:] = rax * mim np.add(ts, ramps, ts) np.add(ts, ts_mean, ts)
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)