def spectrum_of_largest(points, faces, spectrum_size=10, exclude_labels=[-1], normalization=None, areas=None): """ Compute Laplace-Beltrami spectrum on largest connected segment. In case a surface patch is fragmented, we select the largest fragment, remove extraneous triangular faces, and reindex indices. Parameters ---------- points : list of lists of 3 floats x,y,z coordinates for each vertex of the structure faces : list of lists of 3 integers 3 indices to vertices that form a triangle on the mesh spectrum_size : integer number of eigenvalues to be computed (the length of the spectrum) exclude_labels : list of integers background values to exclude normalization : string the method used to normalize eigenvalues ('area' or None) if "area", use area of the 2D structure as in Reuter et al. 2006 areas : numpy array or list of floats (or None) surface area scalar values for all vertices Returns ------- spectrum : list first spectrum_size eigenvalues for Laplace-Beltrami spectrum Examples -------- >>> # Spectrum for left postcentral + pars triangularis pial surfaces: >>> import os >>> import numpy as np >>> from mindboggle.utils.io_vtk import read_scalars, read_vtk, write_vtk >>> from mindboggle.utils.mesh import remove_faces, reindex_faces_points >>> from mindboggle.shapes.laplace_beltrami import spectrum_of_largest >>> path = os.environ['MINDBOGGLE_DATA'] >>> label_file = os.path.join(path, 'arno', 'labels', 'lh.labels.DKT31.manual.vtk') >>> area_file = os.path.join(path, 'arno', 'shapes', 'lh.pial.area.vtk') >>> spectrum_size = 6 >>> exclude_labels = [-1] >>> normalization = None >>> faces, lines, indices, points, u1, labels, u2,u3 = read_vtk(label_file, >>> return_first=True, return_array=True) >>> I20 = [i for i,x in enumerate(labels) if x==20] # pars triangularis >>> I22 = [i for i,x in enumerate(labels) if x==22] # postcentral >>> I22.extend(I20) >>> faces = remove_faces(faces, I22) >>> faces, points, o1 = reindex_faces_points(faces, points) >>> areas, u1 = read_scalars(area_file, True, True) >>> # >>> spectrum_of_largest(points, faces, spectrum_size, exclude_labels, >>> normalization, areas) [6.3469513010430304e-18, 0.0005178862383467463, 0.0017434911095630772, 0.003667561767487686, 0.005429017880363784, 0.006309346984678924] >>> # View both segments: >>> from mindboggle.utils.plots import plot_surfaces >>> scalars = np.zeros(np.shape(labels)) >>> scalars[I22] = 1 >>> vtk_file = 'test_two_labels.vtk' >>> write_vtk(vtk_file, points, indices, lines, faces, >>> scalars, scalar_names='scalars', scalar_type='int') >>> plot_surfaces(vtk_file) """ from scipy.sparse.linalg import eigsh, lobpcg import numpy as np from mindboggle.utils.segment import select_largest from mindboggle.shapes.laplace_beltrami import fem_laplacian if isinstance(areas, list): areas = np.array(areas) # Check to see if there are enough points: min_points_faces = spectrum_size npoints = len(points) if npoints < min_points_faces or len(faces) < min_points_faces: print("The input size {0} ({1} faces) should be much larger " "than spectrum_size ({2})". format(npoints, len(faces), spectrum_size)) return None else: #--------------------------------------------------------------------- # Select the largest segment (connected set of indices): #--------------------------------------------------------------------- points, faces = select_largest(points, faces, exclude_labels, areas, reindex=True) # Alert if the number of indices is small: if len(points) < min_points_faces: print("The input size {0} is too small.".format(len(points))) return None elif faces: #----------------------------------------------------------------- # Compute spectrum: #----------------------------------------------------------------- spectrum = fem_laplacian(points, faces, spectrum_size, normalization) return spectrum else: return None
def zernike_moments_of_largest(points, faces, order=20, exclude_labels=[-1], areas=None): """ Compute the Zernike moments on largest connected segment. In case a surface patch is fragmented, we select the largest fragment, remove extraneous triangular faces, and reindex indices. Parameters ---------- points : list of lists of 3 floats x,y,z coordinates for each vertex of the structure faces : list of lists of 3 integers 3 indices to vertices that form a triangle on the mesh order : integer number of moments to compute exclude_labels : list of integers labels to be excluded areas : numpy array or list of floats (or None) surface area scalar values for all vertices Returns ------- descriptors : list of floats Zernike descriptors of largest connected segment Examples -------- >>> # Zernike moments for one label (artificial composite), two fragments: >>> import os >>> import numpy as np >>> from mindboggle.utils.io_vtk import read_scalars, read_vtk, write_vtk >>> from mindboggle.utils.mesh import remove_faces >>> from mindboggle.shapes.zernike.zernike import zernike_moments_of_largest >>> path = os.environ['MINDBOGGLE_DATA'] >>> area_file = os.path.join(path, 'arno', 'shapes', 'lh.pial.area.vtk') >>> label_file = os.path.join(path, 'arno', 'labels', 'lh.labels.DKT31.manual.vtk') >>> order = 3 >>> exclude_labels = [-1] >>> faces, lines, indices, points, u1, labels, u2,u3 = read_vtk(label_file, >>> return_first=True, return_array=True) >>> I19 = [i for i,x in enumerate(labels) if x==19] # pars orbitalis >>> I22 = [i for i,x in enumerate(labels) if x==22] # postcentral >>> I19.extend(I22) >>> faces = remove_faces(faces, I19) >>> areas, u1 = read_scalars(area_file, True, True) >>> # >>> zernike_moments_of_largest(points, faces, order, exclude_labels, areas) [7562.751480397972, 143262239.5171249, 1107670.7893994227, 28487908892.820065, 112922387.17238183, 10250734140.30357] >>> # View two fragments: >>> from mindboggle.utils.plots import plot_vtk >>> scalars = np.zeros(np.shape(labels)) >>> scalars[I19] = 1 >>> vtk_file = 'test_two_labels.vtk' >>> write_vtk(vtk_file, points, indices, lines, faces, >>> scalars, scalar_names='scalars') >>> plot_vtk(vtk_file) """ import numpy as np from mindboggle.utils.segment import select_largest from mindboggle.shapes.zernike.zernike import zernike_moments if isinstance(areas, list): areas = np.array(areas) # Check to see if there are enough points: min_npoints = order npoints = len(points) if npoints < min_npoints or len(faces) < min_npoints: print("The input size {0} ({1} faces) should be larger " "than order {2}".format(npoints, len(faces), order)) return None else: # --------------------------------------------------------------------- # Select the largest segment (connected set of indices): # --------------------------------------------------------------------- points, faces = select_largest(points, faces, exclude_labels, areas, reindex=True) # Alert if the number of indices is small: if len(points) < min_npoints: print("The input size {0} is too small.".format(len(points))) return None elif faces: # ----------------------------------------------------------------- # Compute Zernike moments: # ----------------------------------------------------------------- descriptors = zernike_moments(points, faces, order) return descriptors else: return None