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
def run(self, image): # Make sure it's an asems image if not hasattr(image, "asym_times") and not hasattr(image, "te"): self.log("No asym_time, can't compute field map.") return asym_times = image.asym_times # Make sure there are at least two volumes if image.tdim < 2: self.log("Cannot calculate field map from only a single volume."\ " Must have at least two volumes.") return diffshape = (image.tdim-1,) + image.shape[-3:] diffshape = image.tdim > 2 and diffshape or diffshape[-3:] phase_map = image._subimage(np.zeros(diffshape, np.float32)) bytemask = image._subimage(np.zeros(diffshape, np.float32)) # Get phase difference between scan n+1 and scan n # Then find the mask and unwrapped phase, and compute # the field strength in terms of rad/s fwhm = max(image.isize, image.jsize) * 1.5 for psub, msub in zip(phase_map, bytemask): del_te = asym_times[msub.num+1] - asym_times[msub.num] if self.haschans: for c in range(image.n_chan): image.load_chan(c) dphs = image[msub.num+1] * np.conjugate(image[msub.num]) msk = build_3Dmask(np.power(np.abs(dphs), 0.5), self.threshfactor) msub[:] += msk ## psub[:] += (unwrap3D(np.angle(dphs)) * msk) #/ del_te ## psub[:] += gaussian_smooth(np.angle(dphs), 1.5, 3) ## smooth_phs = unwrap3D(gaussian_smooth(np.angle(dphs), ## sigma_y, sigma_x, ## gaussian_dims))*msk smooth_phs = ReconImage(np.angle(dphs), isize=image.isize, jsize=image.jsize) GaussianSmooth(fwhm=fwhm).run(smooth_phs) psub[:] += smooth_phs[:] #psub[:] = np.where(msub[:], psub[:]/msub[:], 0) psub[:] /= image.n_chan msub[:] = np.where(msub[:], 1, 0) #psub[:] = (unwrap3D(psub[:]) * msub[:]) #/ del_te image.use_membuffer(0) else: dphs = image[msub.num+1] * np.conjugate(image[msub.num]) msub[:] = build_3Dmask(np.power(np.abs(dphs), 0.5), self.threshfactor) #psub[:] = (unwrap3D(np.angle(dphs)) * msub[:]) #/ del_te psub[:] = np.angle(dphs) GaussianSmooth(fwhm=fwhm).run(psub) psub[:] = unwrap3D(psub[:])*msub[:] psub[:] /= del_te # for each diff vol, write a file with vol0 = fmap, vol1 = mask fmap_file = clean_name(self.fmap_file)[0] if phase_map.ndim > 3: for index in range(phase_map.tdim): catIm = phase_map.subImage(index).concatenate( bytemask.subImage(index), newdim=True) catIm.writeImage(fmap_file+"-%d"%index, format_type="nifti-single") else: catIm = phase_map.concatenate(bytemask, newdim=True) catIm.writeImage(fmap_file, format_type="nifti-single")
def run(self, image): # Make sure it's an asems image if not hasattr(image, "asym_times") and not hasattr(image, "te"): self.log("No asym_time, can't compute field map.") return asym_times = image.asym_times # Make sure there are at least two volumes if image.tdim < 2: self.log("Cannot calculate field map from only a single volume."\ " Must have at least two volumes.") return diffshape = (image.tdim - 1, ) + image.shape[-3:] diffshape = image.tdim > 2 and diffshape or diffshape[-3:] phase_map = image._subimage(np.zeros(diffshape, np.float32)) bytemask = image._subimage(np.zeros(diffshape, np.float32)) # Get phase difference between scan n+1 and scan n # Then find the mask and unwrapped phase, and compute # the field strength in terms of rad/s fwhm = max(image.isize, image.jsize) * 1.5 for psub, msub in zip(phase_map, bytemask): del_te = asym_times[msub.num + 1] - asym_times[msub.num] if self.haschans: for c in range(image.n_chan): image.load_chan(c) dphs = image[msub.num + 1] * np.conjugate(image[msub.num]) msk = build_3Dmask(np.power(np.abs(dphs), 0.5), self.threshfactor) msub[:] += msk ## psub[:] += (unwrap3D(np.angle(dphs)) * msk) #/ del_te ## psub[:] += gaussian_smooth(np.angle(dphs), 1.5, 3) ## smooth_phs = unwrap3D(gaussian_smooth(np.angle(dphs), ## sigma_y, sigma_x, ## gaussian_dims))*msk smooth_phs = ReconImage(np.angle(dphs), isize=image.isize, jsize=image.jsize) GaussianSmooth(fwhm=fwhm).run(smooth_phs) psub[:] += smooth_phs[:] #psub[:] = np.where(msub[:], psub[:]/msub[:], 0) psub[:] /= image.n_chan msub[:] = np.where(msub[:], 1, 0) #psub[:] = (unwrap3D(psub[:]) * msub[:]) #/ del_te image.use_membuffer(0) else: dphs = image[msub.num + 1] * np.conjugate(image[msub.num]) msub[:] = build_3Dmask(np.power(np.abs(dphs), 0.5), self.threshfactor) #psub[:] = (unwrap3D(np.angle(dphs)) * msub[:]) #/ del_te psub[:] = np.angle(dphs) GaussianSmooth(fwhm=fwhm).run(psub) psub[:] = unwrap3D(psub[:]) * msub[:] psub[:] /= del_te # for each diff vol, write a file with vol0 = fmap, vol1 = mask fmap_file = clean_name(self.fmap_file)[0] if phase_map.ndim > 3: for index in range(phase_map.tdim): catIm = phase_map.subImage(index).concatenate( bytemask.subImage(index), newdim=True) catIm.writeImage(fmap_file + "-%d" % index, format_type="nifti-single") else: catIm = phase_map.concatenate(bytemask, newdim=True) catIm.writeImage(fmap_file, format_type="nifti-single")