Example #1
0
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)
Example #2
0
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)
Example #3
0
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)
Example #4
0
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)
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
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
Example #9
0
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
Example #12
0
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
Example #13
0
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
Example #14
0
 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
Example #17
0
def func_minimize_adhoc(init_hemisphere, num_iterations):
    opt = sphere.disperse_charges(init_hemisphere, num_iterations)[0]
    return opt.vertices
Example #18
0
    # 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)