Exemple #1
0
 def test_flat_triangular_mesh(self):
     data = np.loadtxt("data/flat_triangular_mesh.txt", skiprows=1)
     vertices = data[0:121].astype(np.float64)
     triangles = data[121:].astype(np.int32)
     distances = gdist.local_gdist_matrix(vertices, triangles)
     epsilon = 1e-6  # the default value used in `assert_array_almost_equal`
     # test if the obtained matrix is symmetric
     assert (abs(distances - distances.T) > epsilon).nnz == 0
     np.testing.assert_array_almost_equal(distances.toarray()[1][0], 0.2)
     # set max distance as 0.3
     distances = gdist.local_gdist_matrix(vertices, triangles, 0.3)
     # test if the obtained matrix is symmetric
     assert (abs(distances - distances.T) > epsilon).nnz == 0
     assert np.max(distances) <= 0.3
Exemple #2
0
 def test_hedgehog_mesh(self):
     data = np.loadtxt("data/hedgehog_mesh.txt", skiprows=1)
     vertices = data[0:300].astype(np.float64)
     triangles = data[300:].astype(np.int32)
     distances = gdist.local_gdist_matrix(vertices, triangles)
     epsilon = 1e-6  # the default value used in `assert_array_almost_equal`
     # test if the obtained matrix is symmetric
     assert (abs(distances - distances.T) > epsilon).nnz == 0
     np.testing.assert_array_almost_equal(distances.toarray()[1][0],
                                          1.40522)
     # set max distance as 1.45
     distances = gdist.local_gdist_matrix(vertices, triangles, 1.45)
     # test if the obtained matrix is symmetric
     assert (abs(distances - distances.T) > epsilon).nnz == 0
     assert np.max(distances) <= 1.45
def Farthest_Point_Sampling(mesh_name,n):
    """
    add the new farest point to set and print n out of all of mesh
    :param mesh_name:
    :param n:
    :return:
    """
    mesh = read(mesh_name + ".ply")
    v, f = (np.array(mesh.points), np.array(mesh.cells_dict['triangle'], dtype=np.int32))
    geodesics_dist = gdist.local_gdist_matrix(v.astype(np.float64), f.astype(np.int32))

    mesh = Mesh(v=v,f=f)
    mesh.render_pointcloud(scalar_function=mesh.gaussianCurvature())

    s=[]
    s.append(np.random.randint(0, len(v)))
    while (len(s)!=n):
        max_dist = 0
        selected_v = None
        for i,v_i in enumerate(v):
            min_by_s = np.inf
            for s_i in s: #get minimum ovver all s_i
                dist = geodesics_dist[s_i][v_i]
                if dist < min_by_s:
                    min_by_s = dist
            if min_by_s > max_dist:
                max_dist = min_by_s
                selected_v = v_i

        v = np.delete(v,selected_v) #dont iterate v over this node anymore
        s.append(selected_v)
    f_new=gen_f(s)
    mesh = Mesh(v=v[np.array(s)], f=f_new)
    mesh.render_pointcloud(scalar_function=mesh.gaussianCurvature())
def compute_errors(mesh_name, mds, mds_str='mds', embedded_dim=2, snap=True):
    """
    solve 1.4 to calc MDS and geodestic and return normed distance
    :param mesh_name:
    :param mds:
    :param mds_str:
    :param embedded_dim:
    :param snap:
    :return:
    """
    # Load mesh from .ply file
    ply = meshio.read(mesh_name + ".ply")
    v,f = ply.points,ply.cells_dict['triangle']

    if snap:
        geodesics_dist = scipy.sparse.load_npz(mesh_name + '.npz').todense()
    else:
        geodesics_dist = gdist.local_gdist_matrix(v.astype(np.float64), f.astype(np.int32))
        scipy.sparse.save_npz(mesh_name + '.npz', csr_matrix(geodesics_dist))
    # to present original mesh
    """mesh_class = Mesh(v=vertices, f=faces)
    mesh_class.render_pointcloud(scalar_function=geodesics_dist[:],snap_name = path + " Mesh")"""

    if snap:
        if mds_str == 'mds':
            emb_coordinates = scipy.sparse.load_npz(mesh_name + '_MDS_NO_G.npz').todense()
            emb_coordinates = np.abs(emb_coordinates)
        # for sphere
        else:
            emb_coordinates = scipy.sparse.load_npz(mesh_name + '_SPHER_MDS_NO_G.npz').todense()
            emb_coordinates = np.abs(emb_coordinates)
            out = np.zeros((emb_coordinates.shape[0], 3))
            out[:, :2] = +emb_coordinates
            emb_coordinates = out
            embedded_geodesics_dist = scipy.sparse.load_npz(mesh_name + mds_str + '.npz').todense()
    else:
        emb_coordinates = mds(geodesics_dist, embedded_dim)
        embedded_geodesics_dist = gdist.local_gdist_matrix(np.array(emb_coordinates).astype(np.float64),
                                                           f.astype(np.int32))
        scipy.sparse.save_npz(mesh_name + mds_str + '.npz', csr_matrix(embedded_geodesics_dist))
    # present the mesh of embeded:
    """embedded_mesh = Mesh(v=emb_coordinates, f=ply.cells_dict['triangle'])
    embedded_mesh.render_pointcloud(scalar_function=np.sum(embedded_geodesics_dist,axis=1)/len(vertices), snap_name = path + " Mesh using " + method_str)"""
    err = np.linalg.norm(geodesics_dist - embedded_geodesics_dist)
    return err / len(v)
Exemple #5
0
def compute_gdist_mat(surf_name='pial', max_distance=40.0):
    max_distance = float(max_distance)  # in case passed from sys.argv
    for h in 'rl':
        surf_path = '%s/%s/surf/%sh.%s' % (SUBJECTS_DIR, SUBJECT, h, surf_name)
        v, f = nibabel.freesurfer.read_geometry(surf_path)
        mat_path = '%s/%s/surf/%sh.%s.gdist.mat' % (SUBJECTS_DIR, SUBJECT, h,
                                                    surf_name)
        mat = gdist.local_gdist_matrix(v, f.astype('<i4'), max_distance=40.0)
        scipy.io.savemat(mat_path, {'gdist': mat})
Exemple #6
0
 def compute_gdist_mat(self, surf_name='pial', max_distance=40.0):
     "Compute sparse geodesic distance matrix and save in MATLAB format."
     max_distance = float(max_distance)  # in case passed from sys.argv
     for h in 'rl':
         surf_path = '%s/%s/surf/%sh.%s' % (self.subjects_dir, self.subject,
                                            h, surf_name)
         v, f = nibabel.freesurfer.read_geometry(surf_path)
         mat_path = '%s/%s/surf/%sh.%s.gdist.mat' % (
             self.subjects_dir, self.subject, h, surf_name)
         mat = gdist.local_gdist_matrix(v,
                                        f.astype('<i4'),
                                        max_distance=max_distance)
         scipy.io.savemat(mat_path, {'gdist': mat})
Exemple #7
0
    def compute_sparse_matrix(self):
        """
        NOTE: Before calling this method, the surface field
        should already be set on the local connectivity.

        Computes the sparse matrix for this local connectivity.
        """
        if self.surface is None:
            msg = " Before calling 'compute_sparse_matrix' method, the surface field should already be set."
            LOG.error(msg)
            raise Exception(msg)

        self.matrix = gdist.local_gdist_matrix(self.surface.vertices.astype(numpy.float64),
                                               self.surface.triangles.astype(numpy.int32), max_distance=self.cutoff)
Exemple #8
0
 def compute_gdist_mat(self, surf_name='pial', max_distance=40.0):
     max_distance = float(max_distance)  # in case passed from sys.argv
     for h in 'rl':
         subjects_dir = os.environ['SUBJECTS_DIR']
         subject = os.environ['SUBJECT']
         surf_path = '%s/%s/surf/%sh.%s' % (subjects_dir, subject, h,
                                            surf_name)
         surface = IOUtils.read_surface(surf_path, False)
         mat_path = '%s/%s/surf/%sh.%s.gdist.mat' % (subjects_dir, subject,
                                                     h, surf_name)
         mat = gdist.local_gdist_matrix(surface.vertices,
                                        surface.triangles.astype('<i4'),
                                        max_distance=max_distance)
         scipy.io.savemat(mat_path, {'gdist': mat})
    def compute_sparse_matrix(self):
        """
        NOTE: Before calling this method, the surface field
        should already be set on the local connectivity.

        Computes the sparse matrix for this local connectivity.
        """
        if self.surface is None:
            msg = " Before calling 'compute_sparse_matrix' method, the surface field should already be set."
            LOG.error(msg)
            raise Exception(msg)

        self.matrix = gdist.local_gdist_matrix(self.surface.vertices.astype(numpy.float64),
                                               self.surface.triangles.astype(numpy.int32), max_distance=self.cutoff)
Exemple #10
0
    def compute_gdist_mat(self, surf_name: str='pial', max_distance: float=40.0) -> numpy.ndarray:
        max_distance = float(max_distance)  # in case passed from sys.argv
        for h in 'rl':
            subjects_dir = os.environ['SUBJECTS_DIR']
            subject = os.environ['SUBJECT']
            surf_path = '%s/%s/surf/%sh.%s' % (subjects_dir,
                                               subject, h, surf_name)
            surface = IOUtils.read_surface(surf_path, False)
            mat_path = '%s/%s/surf/%sh.%s.gdist.mat' % (
                subjects_dir, subject, h, surf_name)
            mat = gdist.local_gdist_matrix(
                surface.vertices, surface.triangles.astype('<i4'), max_distance=max_distance)
            scipy.io.savemat(mat_path, {'gdist': mat})

            return mat
Exemple #11
0
def local_gdist_matrix(mesh, max_geodist):
    """
    For every vertex, get all the vertices within the maximum distance.
    NOTE: It will take some time to compute all the geo-distance from point to
     point.
    Details about the computing time and memory see in method
    gdist.local_gdist_matrix
    :param mesh:
    :param max_geodist:
    :return:
    """

    vert = mesh.vertices
    poly = mesh.faces.astype(np.int32)

    return gdist.local_gdist_matrix(vert, poly, max_geodist)
Exemple #12
0
    def compute_geodesic_distance_matrix(self, max_dist):
        """
        Calculate a sparse matrix of the geodesic distance from each vertex to
        all vertices within max_dist of them on the surface,

        ``max_dist``: find the distance to vertices out as far as max_dist.

        NOTE: Compute time increases rapidly with max_dist and the memory
        efficiency of the sparse matrices decreases, so, don't use too large a
        value for max_dist...

        """
        dist = gdist.local_gdist_matrix(self.vertices.astype(numpy.float64),
                                        self.triangles.astype(numpy.int32),
                                        max_distance=max_dist)

        self.geodesic_distance_matrix = dist
def test_equality_with_stable():
    surface_datas = ["inner_skull_642", "outer_skull_642", "scalp_1082"]
    for surface_data in surface_datas:
        expected = np.loadtxt(
            f"data/surface_data/{surface_data}/gdist_matrix.txt")
        vertices = np.loadtxt(
            f"data/surface_data/{surface_data}/vertices.txt",
            dtype=np.float64,
        )
        triangles = np.loadtxt(
            f"data/surface_data/{surface_data}/triangles.txt",
            dtype=np.int32,
        )
        actual = gdist.local_gdist_matrix(
            vertices=vertices,
            triangles=triangles,
        )
        actual = actual.toarray()
        np.testing.assert_array_almost_equal(actual, expected)
Exemple #14
0
def getRadialGeodesicPatches(mesh, radius, add_self_loops=True, to_csr=False):
    try:
        import gdist
    except ModuleNotFoundError:
        raise ModuleNotFoundError(
            "The dependency 'gdist' is required for this functionality!")

    V = mesh.vertices.astype(np.float64)
    F = mesh.faces.astype(np.int32)

    patches = gdist.local_gdist_matrix(V, F, max_distance=radius)

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")

        if add_self_loops:
            patches.setdiag(-1)

        if to_csr:
            patches = patches.tocsr()

    return patches
    def compute_geodesic_distance_matrix(self, max_dist):
        """
        Calculate a sparse matrix of the geodesic distance from each vertex to 
        all vertices within max_dist of them on the surface, 

        ``max_dist``: find the distance to vertices out as far as max_dist.

        NOTE: Compute time increases rapidly with max_dist and the memory 
        efficiency of the sparse matrices decreases, so, don't use too large a 
        value for max_dist...

        """
        #TODO: Probably should check that max_dist isn't "too" large or too 
        #      small, min should probably be max edge length...

        #if NO_GEODESIC_DISTANCE:
        #    LOG.error("%s: The geodesic distance library didn't load" % repr(self))
        #    return

        dist = gdist.local_gdist_matrix(self.vertices.astype(numpy.float64),
                                        self.triangles.astype(numpy.int32),
                                        max_distance=max_dist)

        self.geodesic_distance_matrix = dist
Exemple #16
0
    def compute_geodesic_distance_matrix(self, max_dist):
        """
        Calculate a sparse matrix of the geodesic distance from each vertex to 
        all vertices within max_dist of them on the surface, 

        ``max_dist``: find the distance to vertices out as far as max_dist.

        NOTE: Compute time increases rapidly with max_dist and the memory 
        efficiency of the sparse matrices decreases, so, don't use too large a 
        value for max_dist...

        """
        #TODO: Probably should check that max_dist isn't "too" large or too 
        #      small, min should probably be max edge length...

        #if NO_GEODESIC_DISTANCE:
        #    LOG.error("%s: The geodesic distance library didn't load" % repr(self))
        #    return

        dist = gdist.local_gdist_matrix(self.vertices.astype(numpy.float64),
                                        self.triangles.astype(numpy.int32),
                                        max_distance=max_dist)

        self.geodesic_distance_matrix = dist
Exemple #17
0
def local_gdist_matrix_wrapper(verts, triangles, max_distance, queue):
    mtx = gdist.local_gdist_matrix(verts.astype(np.float64), triangles.astype(np.int32), max_distance)
    queue.put(mtx)
Exemple #18
0
def geodesic_distance(pos,
                      face,
                      src=None,
                      dest=None,
                      norm=True,
                      max_distance=None):
    r"""Computes (normalized) geodesic distances of a mesh given by :obj:`pos`
    and :obj:`face`. If :obj:`src` and :obj:`dest` are given, this method only
    computes the geodesic distances for the respective source and target
    node-pairs.

    .. note::

        This function requires the :obj:`gdist` package.
        To install, run :obj:`pip install cython && pip install gdist`.

    Args:
        pos (Tensor): The node positions.
        face (LongTensor): The face indices.
        src (LongTensor, optional): If given, only compute geodesic distances
            for the specified source indices. (default: :obj:`None`)
        dest (LongTensor, optional): If given, only compute geodesic distances
            for the specified target indices. (default: :obj:`None`)
        norm (bool, optional): Normalizes geodesic distances by
            :math:`\sqrt{\textrm{area}(\mathcal{M})}`. (default: :obj:`True`)
        max_distance (float, optional): If given, only yields results for
            geodesic distances less than :obj:`max_distance`. This will speed
            up runtime dramatically. (default: :obj:`None`)

    :rtype: Tensor
    """

    if gdist is None:
        raise ImportError('Package `gdist` could not be found.')

    max_distance = float('inf') if max_distance is None else max_distance

    if norm:
        area = (pos[face[1]] - pos[face[0]]).cross(pos[face[2]] - pos[face[0]])
        norm = (area.norm(p=2, dim=1) / 2).sum().sqrt().item()
    else:  # pragma: no cover
        norm = 1.0

    dtype = pos.dtype

    pos = pos.detach().cpu().to(torch.double).numpy()
    face = face.detach().t().cpu().to(torch.int).numpy()

    if src is None and dest is None:
        out = torch.from_numpy(
            gdist.local_gdist_matrix(pos, face, max_distance * norm).toarray()
            / norm).to(dtype)
    else:
        if src is None:
            src = np.arange(pos.size(0), dtype=np.int32)
        else:
            src = src.detach().cpu().to(torch.int).numpy()

        dest = None if dest is None else dest.detach().cpu().to(
            torch.int).numpy()
        outs = []
        for i in range(len(src)):
            s = src[i:i + 1]
            d = None if dest is None else dest[i:i + 1]

            out = gdist.compute_gdist(pos, face, s, d,
                                      max_distance * norm) / norm
            out = torch.from_numpy(out).to(dtype)
            outs.append(out)

        out = torch.cat(outs, dim=0)

        if dest is None:
            out = out.view(-1, pos.shape[0])

    return out
Exemple #19
0
complex_file = '/scr/ilz3/myelinconnect/struct/surf_%s/orig/mid_surface/%s_%s_mid.vtk'%(hemi, sub, hemi)
simple_file = '/scr/ilz3/myelinconnect/groupavg/indv_space/%s/lowres_%s_d_def.vtk'%(sub, hemi)# version d

complex_v, complex_f, complex_d = read_vtk(complex_file)
complex_vertices = complex_v.astype(np.float64)
complex_faces = complex_f.astype(np.int32)

simple_v, simple_f, simple_d = read_vtk(simple_file)
simple_vertices = simple_v.astype(np.float64)
simple_faces = simple_f.astype(np.int32)

complex_radius = 2 

print time.ctime()
complex_matrix=gdist.local_gdist_matrix(complex_vertices, complex_faces, max_distance=complex_radius)

for sv in range(len(simple_v.shape[0])):
    dist = 1000000
    for cv in range(len(complex_v.shape[0])):
        if sv in complex_matrix[:,cv].indices:
            dist_now = complex_matrix[:,cv][sv].data
            if dist_now < dist:
                dist = dist_now
                


quatsch, need to tunr around
             
#    inradius=list(complex_matrix[:,v].indices)
    # find
Exemple #20
0
from vtk_rw import read_vtk
import numpy as np
import gdist


mesh_file="/scr/ilz3/myelinconnect/new_groupavg/surfs/lowres/%s_lowres_new.vtk"
hemis=['rh', 'lh']

for hemi in hemis:
    v, f, _ = read_vtk(mesh_file %hemi)
    
    v = v.astype(np.float64)
    f = f.astype(np.int32)
    dist_matrix=gdist.local_gdist_matrix(v, f)
Exemple #21
0
def geodesic_distance(pos,
                      face,
                      src=None,
                      dest=None,
                      norm=True,
                      max_distance=None,
                      num_workers=0):
    r"""Computes (normalized) geodesic distances of a mesh given by :obj:`pos`
    and :obj:`face`. If :obj:`src` and :obj:`dest` are given, this method only
    computes the geodesic distances for the respective source and target
    node-pairs.

    .. note::

        This function requires the :obj:`gdist` package.
        To install, run :obj:`pip install cython && pip install gdist`.

    Args:
        pos (Tensor): The node positions.
        face (LongTensor): The face indices.
        src (LongTensor, optional): If given, only compute geodesic distances
            for the specified source indices. (default: :obj:`None`)
        dest (LongTensor, optional): If given, only compute geodesic distances
            for the specified target indices. (default: :obj:`None`)
        norm (bool, optional): Normalizes geodesic distances by
            :math:`\sqrt{\textrm{area}(\mathcal{M})}`. (default: :obj:`True`)
        max_distance (float, optional): If given, only yields results for
            geodesic distances less than :obj:`max_distance`. This will speed
            up runtime dramatically. (default: :obj:`None`)
        num_workers (int, optional): How many subprocesses to use for
            calculating geodesic distances.
            :obj:`0` means that computation takes place in the main process.
            :obj:`-1` means that the available amount of CPU cores is used.
            (default: :obj:`0`)

    :rtype: Tensor
    """
    import gdist

    max_distance = float('inf') if max_distance is None else max_distance

    if norm:
        area = (pos[face[1]] - pos[face[0]]).cross(pos[face[2]] - pos[face[0]])
        norm = (area.norm(p=2, dim=1) / 2).sum().sqrt().item()
    else:
        norm = 1.0

    dtype = pos.dtype

    pos = pos.detach().cpu().to(torch.double).numpy()
    face = face.detach().t().cpu().to(torch.int).numpy()

    if src is None and dest is None:
        out = gdist.local_gdist_matrix(pos, face,
                                       max_distance * norm).toarray() / norm
        return torch.from_numpy(out).to(dtype)

    if src is None:
        src = np.arange(pos.shape[0], dtype=np.int32)
    else:
        src = src.detach().cpu().to(torch.int).numpy()

    dest = None if dest is None else dest.detach().cpu().to(torch.int).numpy()

    def _parallel_loop(pos, face, src, dest, max_distance, norm, i, dtype):
        s = src[i:i + 1]
        d = None if dest is None else dest[i:i + 1]
        out = gdist.compute_gdist(pos, face, s, d, max_distance * norm) / norm
        return torch.from_numpy(out).to(dtype)

    num_workers = mp.cpu_count() if num_workers <= -1 else num_workers
    if num_workers > 0:
        with mp.Pool(num_workers) as pool:
            outs = pool.starmap(
                _parallel_loop,
                [(pos, face, src, dest, max_distance, norm, i, dtype)
                 for i in range(len(src))])
    else:
        outs = [
            _parallel_loop(pos, face, src, dest, max_distance, norm, i, dtype)
            for i in range(len(src))
        ]

    out = torch.cat(outs, dim=0)

    if dest is None:
        out = out.view(-1, pos.shape[0])

    return out