def test_disperse_charges(): charges = np.array([[1., 0, 0], [0, 1., 0], [0, 0, 1.]]) d_sphere, pot = disperse_charges(HemiSphere(xyz=charges), 10) nt.assert_array_almost_equal(charges, d_sphere.vertices) a = np.sqrt(3) / 2 charges = np.array([[3. / 5, 4. / 5, 0], [4. / 5, 3. / 5, 0]]) expected_charges = np.array([[0, 1., 0], [1., 0, 0]]) d_sphere, pot = disperse_charges(HemiSphere(xyz=charges), 1000, .2) nt.assert_array_almost_equal(expected_charges, d_sphere.vertices) for ii in xrange(1, len(pot)): #check that the potential of the system is going down nt.assert_(pot[ii] - pot[ii - 1] <= 0) # Check that the disperse_charges does not blow up with a large constant d_sphere, pot = disperse_charges(HemiSphere(xyz=charges), 1000, 20.) nt.assert_array_almost_equal(expected_charges, d_sphere.vertices) for ii in xrange(1, len(pot)): #check that the potential of the system is going down nt.assert_(pot[ii] - pot[ii - 1] <= 0) #check that the function seems to work with a larger number of charges charges = np.arange(21).reshape(7, 3) norms = np.sqrt((charges * charges).sum(-1)) charges = charges / norms[:, None] d_sphere, pot = disperse_charges(HemiSphere(xyz=charges), 1000, .05) for ii in xrange(1, len(pot)): #check that the potential of the system is going down nt.assert_(pot[ii] - pot[ii - 1] <= 0) #check that the resulting charges all lie on the unit sphere d_charges = d_sphere.vertices norms = np.sqrt((d_charges * d_charges).sum(-1)) nt.assert_array_almost_equal(norms, 1)
def test_disperse_charges(): charges = np.array([[1., 0, 0], [0, 1., 0], [0, 0, 1.]]) d_sphere, pot = disperse_charges(HemiSphere(xyz=charges), 10) nt.assert_array_almost_equal(charges, d_sphere.vertices) a = np.sqrt(3)/2 charges = np.array([[3./5, 4./5, 0], [4./5, 3./5, 0]]) expected_charges = np.array([[0, 1., 0], [1., 0, 0]]) d_sphere, pot = disperse_charges(HemiSphere(xyz=charges), 1000, .2) nt.assert_array_almost_equal(expected_charges, d_sphere.vertices) for ii in xrange(1, len(pot)): #check that the potential of the system is either going down or #stayting almost the same nt.assert_(pot[ii] - pot[ii-1] < 1e-12) #check that the function seems to work with a larger number of charges charges = np.arange(21).reshape(7,3) norms = np.sqrt((charges*charges).sum(-1)) charges = charges / norms[:, None] d_sphere, pot = disperse_charges(HemiSphere(xyz=charges), 1000, .05) for ii in xrange(1, len(pot)): #check that the potential of the system is either going down or #stayting almost the same nt.assert_(pot[ii] - pot[ii-1] < 1e-12) #check that the resulting charges all lie on the unit sphere d_charges = d_sphere.vertices norms = np.sqrt((d_charges*d_charges).sum(-1)) nt.assert_array_almost_equal(norms, 1)
def _generate_gradients(ndirs=64, values=[1000, 3000], nb0s=1): """ Automatically generate a `gradient table <http://nipy.org/dipy/examples_built/gradients_spheres.html#example-gradients-spheres>`_ """ import numpy as np from dipy.core.sphere import (disperse_charges, Sphere, HemiSphere) from dipy.core.gradients import gradient_table theta = np.pi * np.random.rand(ndirs) phi = 2 * np.pi * np.random.rand(ndirs) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, potential = disperse_charges(hsph_initial, 5000) values = np.atleast_1d(values).tolist() vertices = hsph_updated.vertices bvecs = vertices.copy() bvals = np.ones(vertices.shape[0]) * values[0] for v in values[1:]: bvecs = np.vstack((bvecs, vertices)) bvals = np.hstack((bvals, v * np.ones(vertices.shape[0]))) for i in range(0, nb0s): bvals = bvals.tolist() bvals.insert(0, 0) bvecs = bvecs.tolist() bvecs.insert(0, np.zeros(3)) return gradient_table(bvals, bvecs)
def _generate_gradients(ndirs=64, values=[1000, 3000], nb0s=1): """ Automatically generate a `gradient table <http://nipy.org/dipy/examples_built/gradients_spheres.html#example-gradients-spheres>`_ """ import numpy as np from dipy.core.sphere import disperse_charges, Sphere, HemiSphere from dipy.core.gradients import gradient_table theta = np.pi * np.random.rand(ndirs) phi = 2 * np.pi * np.random.rand(ndirs) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, potential = disperse_charges(hsph_initial, 5000) values = np.atleast_1d(values).tolist() vertices = hsph_updated.vertices bvecs = vertices.copy() bvals = np.ones(vertices.shape[0]) * values[0] for v in values[1:]: bvecs = np.vstack((bvecs, vertices)) bvals = np.hstack((bvals, v * np.ones(vertices.shape[0]))) for i in range(0, nb0s): bvals = bvals.tolist() bvals.insert(0, 0) bvecs = bvecs.tolist() bvecs.insert(0, np.zeros(3)) return gradient_table(bvals, bvecs)
def generate_bvecs(N, iters=5000): """Generates N bvectors. Uses dipy.core.sphere.disperse_charges to model electrostatic repulsion on a unit sphere. Parameters ---------- N : int The number of bvectors to generate. This should be equal to the number of bvals used. iters : int Number of iterations to run. Returns ------- bvecs : (N,3) ndarray The generated directions, represented as a unit vector, of each gradient. """ theta = np.pi * np.random.rand(N) phi = 2 * np.pi * np.random.rand(N) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, potential = disperse_charges(hsph_initial, iters) bvecs = hsph_updated.vertices return bvecs
def create_sphere(n_pts): theta = np.pi * np.random.rand(n_pts) phi = 2 * np.pi * np.random.rand(n_pts) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, _ = disperse_charges(hsph_initial, 5000) sph = Sphere(xyz=np.vstack((hsph_updated.vertices, -hsph_updated.vertices))) return sph
def genDirs(N): init_dirs = np.random.randn(N, 3) init_dirs /= np.linalg.norm(init_dirs, axis=1)[:, None] init_hemi = HemiSphere(xyz=init_dirs) dirs_hemi, _ = disperse_charges(init_hemi, iters=1000) pts = dirs_hemi.vertices # shifting to z+ hemi pts = pts * np.sign(pts[:, 2])[:, None] return pts
def get_uniform_hemisphere_with_points(action_space: int, seed=42) -> HemiSphere: if seed is not None: np.random.seed(seed) phi = np.pi * np.random.rand(action_space) theta = 2 * np.pi * np.random.rand(action_space) sphere = HemiSphere(theta=theta, phi=phi) # Sphere(theta=theta, phi=phi) sphere, _ = disperse_charges( sphere, 5000) # enforce uniform distribution of our points return sphere
def create_repulsion_sphere(n_points, n_iter): """ Create a sphere using electrostatic repulsion. params: npoints: number of points in the electrostatic repulsion n_iter: number of iterations to optimise energy return: HemiSphere object with n points vertices """ theta = np.pi * np.random.rand(n_points) phi = 2 * np.pi * np.random.rand(n_points) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, energy = disperse_charges(hsph_initial, iters=n_iter) sph = hsph_updated return sph
def create_symmetric_repulsion_sphere(n_points, n_iter): """ Create a full Sphere object using electrostatic repulsion. params: npoints: number of points in the electrostatic repulsion n_iter: number of iterations to optimise energy return: Sphere object with 2*npoints vertices """ theta = np.pi * np.random.rand(n_points) phi = 2 * np.pi * np.random.rand(n_points) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, energy = disperse_charges(hsph_initial, iters=n_iter) sph = Sphere(xyz=np.vstack((hsph_updated.vertices, -hsph_updated.vertices))) return sph
def _qti_gtab(): """Return a gradient table with b0, 2 shells, 30 directions, and linear and planar tensor encoding for fitting QTI.""" np.random.seed(123) n_dir = 30 hsph_initial = HemiSphere(theta=np.pi * np.random.rand(n_dir), phi=2 * np.pi * np.random.rand(n_dir)) hsph_updated, _ = disperse_charges(hsph_initial, 100) directions = hsph_updated.vertices bvecs = np.vstack([np.zeros(3)] + [directions for _ in range(4)]) bvals = np.concatenate((np.zeros(1), np.ones(n_dir), np.ones(n_dir) * 2, np.ones(n_dir), np.ones(n_dir) * 2)) btens = np.array(['LTE' for i in range(1 + n_dir * 2)] + ['PTE' for i in range(n_dir * 2)]) gtab = gradient_table(bvals, bvecs, btens=btens) return gtab
def uniform_toy_data(): toydict = {} n_pts = 64 theta = np.pi * np.random.rand(n_pts) phi = 2 * np.pi * np.random.rand(n_pts) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, potential = disperse_charges(hsph_initial, 5000) vertices = hsph_updated.vertices values = np.ones(vertices.shape[0]) bvecs = np.vstack((vertices)) bvals = np.hstack((1000 * values)) bvecs = np.insert(bvecs, (0, bvecs.shape[0]), np.array([0, 0, 0]), axis=0) bvals = np.insert(bvals, (0, bvals.shape[0]), 0) gtab = gradient_table(bvals, bvecs) toy_voxel = SingleTensor(gtab) toy_data = np.tile(toy_voxel, (11, 11, 11, 1)) toy_tissue_classifier = np.ones(toy_data.shape[:-1]) toy_affine = np.eye(4) # make a slice roi that should track in-plane only toy_roi_long_plane = np.zeros(toy_data.shape[:-1]) toy_roi_long_plane[:, :, 0]=1 # make a slice roi that should track directly across the whole volume toy_roi_radial_plane = np.zeros(toy_data.shape[:-1]) toy_roi_radial_plane[0, :, :] = 1 # make an roi that contains the center voxel only toy_roi_center_vox = np.zeros(toy_data.shape[:-1]) toy_roi_center_vox[5, 5, 5] = 1 toydict['gtab'] = gtab toydict['toy_data'] = toy_data toydict['toy_affine'] = toy_affine toydict['toy_roi_long_plane'] = toy_roi_long_plane toydict['toy_roi_radial_plane'] = toy_roi_radial_plane toydict['toy_roi_center_vox'] = toy_roi_center_vox toydict['toy_tissue_classifier'] = toy_tissue_classifier return toydict
def initialize_dir(self, dir_num, direction_learning, initialization): theta = np.pi * np.random.rand(dir_num) phi = 2 * np.pi * np.random.rand(dir_num) hsph_initial = HemiSphere(theta=theta, phi=phi) if initialization == 'uniform': hsph_updated, potential = disperse_charges(hsph_initial, 5000) # optimize self.theta = torch.nn.Parameter( torch.tensor(hsph_updated.theta).float(), requires_grad=bool(int(direction_learning))) self.phi = torch.nn.Parameter( torch.tensor(hsph_updated.phi).float(), requires_grad=bool(int(direction_learning))) if initialization == 'random': self.theta = torch.nn.Parameter( torch.tensor(hsph_initial.theta).float(), requires_grad=bool(int(direction_learning))) # random self.phi = torch.nn.Parameter( torch.tensor(hsph_initial.phi).float(), requires_grad=bool(int(direction_learning))) return
def __init__(self, device, seeds=None, step_width=0.8, dataset='100307', grid_dim=(3, 3, 3), max_l2_dist_to_state=0.1, tracking_in_RAS=True, fa_threshold=0.1, b_val=1000, odf_state=True, odf_mode="CSD", action_space=100, pFolderBundles="data/gt_bundles/"): print("DEPRECATED! Dont use anymore.") self.state_history = None self.reference_seed_point_ijk = None self.points_visited = None self.past_reward = None self.reward = None self.stepCounter = None self.done = None self.seed_index = None self.step_angles = None self.line = None self.na_reward_history = None self.av_na_reward = None self.past_bundle = None print("Loading dataset # ", dataset) self.device = device preprocessor = DataPreprocessor().normalize().crop(b_val).fa_estimate() if dataset == 'ISMRM': self.dataset = preprocessor.get_ismrm(f"data/ISMRM2015/") else: self.dataset = preprocessor.get_hcp(f"data/HCP/{dataset}/") self.step_width = step_width self.dtype = torch.FloatTensor # vs. torch.cuda.FloatTensor self.dti_model = None self.dti_fit = None self.odf_interpolator = None self.sh_coefficient = None self.odf_mode = odf_mode np.random.seed(42) action_space = action_space phi = np.pi * np.random.rand(action_space) theta = 2 * np.pi * np.random.rand(action_space) sphere = HemiSphere(theta=theta, phi=phi) #Sphere(theta=theta, phi=phi) sphere, _ = disperse_charges( sphere, 5000) # enforce uniform distribtuion of our points self.sphere = sphere self.sphere_odf = sphere # -- interpolation function of state's value -- self.state_interpol_func = self.interpolate_dwi_at_state if odf_state: print("Interpolating ODF as state Value") self.state_interpol_func = self.interpolate_odf_at_state self.directions = torch.from_numpy(self.sphere.vertices).to(device) no_actions, _ = self.directions.shape self.directions_odf = torch.from_numpy( self.sphere_odf.vertices).to(device) self.action_space = Discrete( no_actions) # spaces.Discrete(no_actions+1) self.dwi_postprocessor = Resample( sphere=get_sphere('repulsion100')) # resample(sphere=sphere) self.referenceStreamline_ijk = None self.grid = get_grid(np.array(grid_dim)) self.maxL2dist_to_State = max_l2_dist_to_state self.tracking_in_RAS = tracking_in_RAS # -- load streamlines -- self.fa_threshold = fa_threshold self.maxSteps = 2000 # -- init seeds -- self.seeds = seeds if self.seeds is None: if self.dti_fit is None: self._init_odf() dti_model = dti.TensorModel(self.dataset.gtab, fit_method='LS') dti_fit = dti_model.fit(self.dataset.dwi, mask=self.dataset.binary_mask) fa_img = dti_fit.fa seed_mask = fa_img.copy() seed_mask[seed_mask >= 0.2] = 1 seed_mask[seed_mask < 0.2] = 0 seeds = utils.seeds_from_mask(seed_mask, affine=np.eye(4), density=1) # tracking in IJK self.seeds = torch.from_numpy(seeds) # -- init bundles for neuroanatomical reward -- print("Init tract masks for neuroanatomical reward") fibers = [] self.bundleNames = os.listdir(pFolderBundles) for fibFile in self.bundleNames: pFibre = pFolderBundles + fibFile #print(" @ " + pFibre) fibers.append( FiberBundleDataset(path_to_files=pFibre, dataset=self.dataset).tractMask) self.tractMasksAllBundles = torch.stack(fibers, dim=0).to(self.device) # -- set default values -- self.reset() # -- init observation space -- obs_shape = self.get_observation_from_state(self.state).shape self.observation_space = Box(low=0, high=150, shape=obs_shape)
## Generate semi-well distributed point on the sphere with golden spiral method N = 1000 golden_angle = np.pi * (3 - np.sqrt(5)) theta = golden_angle * np.arange(N) z = np.linspace(1 - 1.0 / N, 1.0 / N - 1, N) radius = np.sqrt(1 - z * z) points = np.zeros((N, 3)) points[:, 0] = radius * np.cos(theta) points[:, 1] = radius * np.sin(theta) points[:, 2] = z ## convert to dipy hemisphere hemi = HemiSphere(xyz=points) res, _ = disperse_charges(hemi, 100) dirs = res.vertices ## get necessary vector to generate the plane planar_dirs = np.zeros((dirs.shape[0], 2, 3)) for idx in range(dirs.shape[0]): # current directions v = dirs[idx] # generate initial non colinear vectors, v1 is v v1, v2, v3 = findLinIndepRandomRot(v) # generate 3 orthonormal vectors, u1 is v normalized u1, u2, u3 = gramSchmidt3(v1, v2, v3) planar_dirs[idx, 0] = u2 planar_dirs[idx, 1] = u3 ## G1G2G3.txt-like structure
def func_minimize_adhoc(init_hemisphere, num_iterations): opt = sphere.disperse_charges(init_hemisphere, num_iterations)[0] return opt.vertices
# 1) Initialize acquisition parameters for 6 first # b-value = 0 bvecs = np.zeros((6, 3)) bvals = np.zeros(6) # 2) Add b-values and gradient directions for the # other acquisition shells for shell_i in range(n_shells[acq_i]): # Sample the evenly distributed directions given # the number of direction of the shell n_pts = pts_matrix[acq_i, shell_i] theta = np.pi * np.random.rand(n_pts) phi = 2 * np.pi * np.random.rand(n_pts) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, potential = disperse_charges(hsph_initial, 5000) directions = hsph_updated.vertices # Add directions to bvecs bvecs = np.vstack((bvecs, directions)) # Add b-values to bvals according to the number of # shell directions b = bval_matrix[acq_i, shell_i] bvals = np.hstack((bvals, b * np.ones(n_pts))) full_bvecs[acq_i, :, :] = bvecs full_bvals[acq_i, :] = bvals # Display progress prog = (acq_i + 1.0) / nacq * 100 time.sleep(1)
# 1) Initialize acquisition parameters for 6 first # b-value = 0 bvecs = np.zeros((6, 3)) bvals = np.zeros(6) # 2) Add b-values and gradient directions for the # other acquisition shells for shell_i in range(n_shells[acq_i]): # Sample the evenly distributed directions given # the number of direction of the shell n_pts = pts_matrix[acq_i, shell_i] theta = np.pi * np.random.rand(n_pts) phi = 2 * np.pi * np.random.rand(n_pts) hsph_initial = HemiSphere(theta=theta, phi=phi) hsph_updated, potential = disperse_charges(hsph_initial, 5000) directions = hsph_updated.vertices # Add directions to bvecs bvecs = np.vstack((bvecs, directions)) # Add b-values to bvals according to the number of # shell directions b = bval_matrix[acq_i, shell_i] bvals = np.hstack((bvals, b * np.ones(n_pts))) full_bvecs[acq_i, :, :] = bvecs full_bvals[acq_i, :] = bvals # Display progress prog = (acq_i+1.0) / nacq * 100 time.sleep(1)