Source code for mr_utils.sim.traj.radial

'''Generate radial sampling masks.'''

import numpy as np
from skimage.morphology import skeletonize
from skimage.transform import rotate

[docs]def radial(shape, num_spokes, theta=None, offset=0, theta0=0, skinny=True, extend=False): '''Create 2d binary radial sampling pattern. Parameters ---------- shape : tuple x,y dimensions of sampling pattern. num_spokes : int Number of spokes to simulate. theta : float, optional Angle between spokes (rad). offset : int, optional Number of angles to skip. theta0 : float, optional Starting angle (rad). skinny : bool, optional Garuantee 1px spoke width. extend : bool, optional Extend spokes to the edge of array. Returns ------- idx : array_like Boolean mask where samples in k-space should be taken. Notes ----- If theta=None, use golden angle. If skinny=True, edges of spokes with large slope may be curved. If extend=False, spokes confined in a circle. ''' # Decide if we want to go all the way to edge of the array or not if extend: mode = 'wrap' else: mode = 'constant' # Use golden angle if no angle given if theta is None: theta = np.pi*(3 - np.sqrt(5)) # initialze binary sampling image idx = np.zeros(shape, dtype=bool) # Create prototype spoke that we'll rotate idx0 = np.zeros(idx.shape, dtype=bool) idx0[int(shape[0]/2), :] = 1 # Create all the spokes for ii in range(num_spokes): # Rotate prototype spoke to desired angle idx1 = rotate(idx0, np.rad2deg(theta*(ii + offset) + theta0), resize=False, mode=mode).astype(bool) # If we want the spokes to gave 1px width if skinny: idx1 = skeletonize(idx1) # Add spoke to sampling mask idx |= idx1 return idx
[docs]def radial_golden_ratio_meshgrid(X, Y, num_spokes): '''Create 2d binary golden angle radial sampling pattern. Parameters ---------- X : array_like X component of meshgrid. Y : array_like T component of meshgrid. num_spokes : int Number of spokes to simulate. Returns ------- samp : array_like Mask of where samples in k-space are taken. Notes ----- Issues: For steep slopes, the spokes don't make it all the way to the edge of the image and they curve (from the skeletonize)... ''' from scipy.ndimage.morphology import binary_dilation N = X.shape[0] h = np.abs(X[0, 1] - X[0, 0]) golden = np.pi*(3 - np.sqrt(5)) samp = np.zeros((N, N)) idx = np.zeros(samp.shape, dtype=bool) for ii in range(num_spokes): # Get spoke m = np.tan(golden*ii) # slope idx0 = np.isclose(Y, m*X, atol=h/2) # But we need to make sure everything is connected -- # sometimes the slope is too large and we get gaps in spoke if np.abs(m) > 1: idx0 = binary_dilation(idx0, iterations=6) idx0 = skeletonize(idx0) # idx0 = binary_erosion(idx0,iterations=1) # plt.title(np.tan(golden*ii)) # plt.imshow(idx0) # plt.show() idx |= idx0 # idx |= rot(golden*ii).dot(x == x) # idx |= (Y == X*np.tan(golden*ii)) # plt.plot(x,np.tan(golden*ii)*x) samp[idx] = 1 return samp
if __name__ == '__main__': pass