def test_sph2car(): x, y, z = sph2car([np.pi / 2], [0], [1]) assert_almost_equal(x, 1, decimal=5) assert_almost_equal(y, 0, decimal=5) assert_almost_equal(z, 0, decimal=5) x, y, z = sph2car([np.pi / 2], [0]) assert_almost_equal(x, 1, decimal=5) assert_almost_equal(y, 0, decimal=5) assert_almost_equal(z, 0, decimal=5)
def uniform_random(N): """Generate points inside the sphere randomly, discard those lying outside the sphere, and project the remaining points to the sphere surface. """ # Try to generate enough points so that, after rejection, there will # be at least N left square_volume = 2**3 sphere_volume = 4 / 3 * np.pi p = 1 / (1 - sphere_volume / square_volume) * 1.1 * N x = np.random.uniform(low=-1, high=1, size=p) y = np.random.uniform(low=-1, high=1, size=p) z = np.random.uniform(low=-1, high=1, size=p) r = np.sqrt(x**2 + y**2 + z**2) mask = ~((r == 0) | (r > 1)) r = r[mask][:N] x = x[mask][:N] y = y[mask][:N] z = z[mask][:N] theta = np.arccos(z / r) phi = np.arctan2(y, x) return coord.sph2car(theta, phi)
def plot_ODF(grid_density=100): theta_grid = np.linspace(0, np.pi, grid_density) phi_grid = np.linspace(0, 2 * np.pi, grid_density) phi_vec, theta_vec = np.meshgrid(phi_grid, theta_grid) phi_vec, theta_vec = phi_vec.ravel(), theta_vec.ravel() xyz = np.column_stack(coord.sph2car(theta_vec, phi_vec)) ODF = w[0] * single_tensor_ODF(xyz, rotation=R0) ODF += w[1] * single_tensor_ODF(xyz, rotation=R1) ODF = ODF.reshape((grid_density, grid_density)) plot.surf_grid_3D(ODF, theta_grid, phi_grid, scale_radius=True)
def saff_kuijlaars(N): """ References ---------- 'Distributing many points on a sphere' by E.B. Saff and A.B.J. Kuijlaars, Mathematical Intelligencer, 19.1 (1997), pp. 5--11 """ k = np.arange(N) h = -1 + 2 * k / (N - 1) theta = np.arccos(h) phi = np.zeros_like(h) for i in range(1, N - 1): phi[i] = (phi[i - 1] + 3.6 / np.sqrt(N * (1 - h[i]**2))) % (2 * np.pi) return coord.sph2car(theta, phi)
#from dipy.data import get_sphere #verts, faces = get_sphere('symmetric724') ## from dipy.core.triangle_subdivide import create_unit_sphere ## verts, edges, sides = create_unit_sphere(5) ## faces = edges[sides, 0] from dipy.core.triangle_subdivide import create_unit_sphere verts, edges, sides = create_unit_sphere(5) faces = edges[sides, 0] theta, phi, r = car2sph(*verts.T) sampling_xyz = np.column_stack( sph2car(coords['gradient_theta'], coords['gradient_phi']) ) ## verts = np.column_stack(sph2car(theta, phi)) ## from dipy.core.meshes import faces_from_vertices ## faces = faces_from_vertices(verts) def separation_from_odf(odf): # Find angles from dipy.reconst.recspeed import local_maxima p, i = local_maxima(odf, edges) p = p[:2] i = i[:2] print "Peaks:", p print "Angular separation:", np.rad2deg(np.arccos(np.abs(np.dot(verts[i[0]], verts[i[1]]))))
def build_coverage(points, fname_miss=None, symm=True): """Compute surface coverage for a set of directions. Parameters ---------- points : string or ndarray File name of file containing a 3xN array of unit vectors, or ndarray with vectors. """ # Norm threshold below which we simply drop vectors assuming they were # noise or zeros (such as B0 term in DWI data) drop_norm = 1e-8 # Load vectors from disk if hasattr(points, '__array_interface__'): bvecs = points else: bvecs = load_bvecs(points) all_idx = np.arange(bvecs.shape[1]) if fname_miss is None: # If no missing directions are given, make an empty 3x0 array so that # later we don't need to constantly special-case code for None bv_good = bvecs bv_miss = np.empty((3,0)) else: # Preprocess the input to read it as a 1-d list while skipping comment # lines. tmp = open(os.path.join(data_path, fname_miss)).read() bad_raw = StringIO(' '.join(l for l in tmp.splitlines() if not l.strip().startswith('#'))) bad_idx = np.loadtxt(bad_raw,int) if bad_idx.ndim==0: # Corner case: if the input file contains a single number, loadtxt # returns an array scalar instead of a 1-element 1-d array. We # need to fix that so code further down doesn't explode bad_idx.shape = (1,) # split the full list between good/bad directions good_idx = np.setdiff1d(all_idx,bad_idx) bv_good = bvecs[:,good_idx] bv_miss = bvecs[:,bad_idx] # The first vector is typically 0, so we drop it if present if vec_norms(bv_good)[0] < drop_norm: bv_good = bv_good[:,1:] # The full bvecs lists contains every vector and its opposite direction if symm: bv_good, bv_miss = symmetrize(bv_good, bv_miss) # Find the total number of bvecs. We do this now rather than taking # len(bvecs) to properly account for the possibly dropped B0 term. nvecs = bv_good.shape[1] + bv_miss.shape[1] # Now compute and draw the coverage field generated by the 'good' # directions # compute scalar field from point distribution bv_good on the # sphere mesh theta, phi = sphere.mesh(closed=True) xyz = np.dstack(coord.sph2car(theta, phi)) field = dwi_coverage(bv_good, xyz, nvecs) return bv_good,sphere,field,bv_miss
b = np.load(bvals) bvecs = np.load(bvecs) bvecs = bvecs[b > 0] b = b[b > 0] theta, phi, _ = coord.car2sph(*bvecs.T) theta_odf, phi_odf = theta132, phi132 kernel = inv_funk_radon_even_kernel kernel_N = 8 X = kernel_matrix(theta, phi, theta_odf, phi_odf, kernel=kernel, N=kernel_N) D = 150 # Grid density for plots (higher => more dense) b = 3000 + np.random.normal(scale=4, size=len(theta)) # Make up somewhat realistic b-values xyz = np.column_stack(coord.sph2car(theta, phi)) sph_io.savez('sphere_pts', gradient_theta=theta, gradient_phi=phi, odf_theta=theta_odf, odf_phi=phi_odf, b=b) # Fiber weights w = [0.5, 0.5] angles = np.deg2rad(np.arange(40, 60, 5)) angles = np.insert(angles, 0, 0) SNR = None for k, gamma in enumerate(angles): print "Angle:", np.rad2deg(gamma)