Exemple #1
0
def select_largest(points, faces, exclude_labels=[-1], areas=None,
                   reindex=True):
    """
    Select the largest segment (connected set of indices) in a mesh.

    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
    exclude_labels : list of integers
        background values to exclude
    areas : numpy array or list of floats (or None)
        surface area scalar values for all vertices
    reindex : Boolean
        reindex indices in faces?

    Returns
    -------
    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

    Examples
    --------
    >>> # Spectrum 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.utils.segment import select_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')
    >>> 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)
    >>> reindex = True
    >>> #
    >>> points, faces = select_largest(points, faces, exclude_labels, areas,
    >>>                                reindex)
    >>> # View:
    >>> 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.mesh import find_neighbors, remove_faces, \
        reindex_faces_points
    from mindboggle.utils.segment import segment

    # Areas:
    use_area = False
    if isinstance(areas, np.ndarray) and np.shape(areas):
        use_area = True
    elif isinstance(areas, list) and len(areas):
        areas = np.array(areas)
        use_area = True

    # Check to see if there are enough points:
    min_npoints = 4
    npoints = len(points)
    if npoints < min_npoints or len(faces) < min_npoints:
        print("The input size {0} ({1} faces) should be much larger "
              "than {2}". format(npoints, len(faces), min_npoints))
        return None
    else:

        #---------------------------------------------------------------------
        # Segment the indices into connected sets of indices:
        #---------------------------------------------------------------------
        # Construct neighbor lists:
        neighbor_lists = find_neighbors(faces, npoints)

        # Determine the indices:
        indices = [x for sublst in faces for x in sublst]

        # Segment:
        segments = segment(indices, neighbor_lists, min_region_size=1,
            seed_lists=[], keep_seeding=False, spread_within_labels=False,
            labels=[], label_lists=[], values=[], max_steps='', verbose=False)

        #---------------------------------------------------------------------
        # Select the largest segment (connected set of indices):
        #---------------------------------------------------------------------
        unique_segments = [x for x in np.unique(segments)
                           if x not in exclude_labels]
        if len(unique_segments) > 1:
            select_indices = []
            max_segment_area = 0
            for segment_number in unique_segments:
                segment_indices = [i for i,x in enumerate(segments)
                                   if x == segment_number]
                if use_area:
                    segment_area = np.sum(areas[segment_indices])
                else:
                    segment_area = len(segment_indices)
                if segment_area > max_segment_area:
                    select_indices = segment_indices
                    max_segment_area = len(select_indices)
            print('Maximum size of {0} segments: {1} vertices'.
                  format(len(unique_segments), len(select_indices)))

            #-----------------------------------------------------------------
            # Extract points and renumber faces for the selected indices:
            #-----------------------------------------------------------------
            faces = remove_faces(faces, select_indices)
        else:
            select_indices = indices

        # Alert if the number of indices is small:
        if len(select_indices) < min_npoints:
            print("The input size {0} is too small.".format(len(select_indices)))
            return None
        elif faces:

            #-----------------------------------------------------------------
            # Reindex indices in faces:
            #-----------------------------------------------------------------
            if reindex:
                faces, points = reindex_faces_points(faces, points)
                return points, faces
            else:
                points = np.array(points)
                points = points[select_indices].tolist()
                return points, faces
        else:
            return None
Exemple #2
0
def plot_mask_surface(vtk_file, mask_file='', nonmask_value=-1,
                      masked_output='', remove_nonmask=False,
                      program='vtkviewer',
                      use_colormap=False, colormap_file=''):
    """
    Use vtkviewer or mayavi2 to visualize VTK surface mesh data.

    If a mask_file is provided, a temporary masked file is saved,
    and it is this file that is viewed.

    If using vtkviewer, can optionally provide colormap file
    or set $COLORMAP environment variable.

    Parameters
    ----------
    vtk_file : string
        name of VTK surface mesh file
    mask_file : string
        name of VTK surface mesh file to mask vtk_file vertices
    nonmask_value : integer
        nonmask (usually background) value
    masked_output : string
        temporary masked output file name
    remove_nonmask : Boolean
        remove vertices that are not in mask? (otherwise assign nonmask_value)
    program : string {'vtkviewer', 'mayavi2'}
        program to visualize VTK file
    use_colormap : Boolean
        use Paraview-style XML colormap file set by $COLORMAP env variable?
    colormap_file : string
        use colormap in given file if use_colormap==True?  if empty and
        use_colormap==True, use file set by $COLORMAP environment variable

    Examples
    --------
    >>> import os
    >>> from mindboggle.utils.plots import plot_mask_surface
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> vtk_file = os.path.join(path, 'arno', 'labels', 'lh.labels.DKT31.manual.vtk')
    >>> mask_file = os.path.join(path, 'test_one_label.vtk')
    >>> nonmask_value = 0 #-1
    >>> masked_output = ''
    >>> remove_nonmask = True
    >>> program = 'vtkviewer'
    >>> use_colormap = True
    >>> colormap_file = '' #'/software/mindboggle_tools/colormap.xml'
    >>> plot_mask_surface(vtk_file, mask_file, nonmask_value, masked_output, remove_nonmask, program, use_colormap, colormap_file)

    """
    import os
    import numpy as np

    from mindboggle.utils.mesh import remove_faces, reindex_faces_points
    from mindboggle.utils.utils import execute
    from mindboggle.utils.plots import plot_surfaces
    from mindboggle.utils.io_vtk import read_scalars, rewrite_scalars, \
                                        read_vtk, write_vtk

    #-------------------------------------------------------------------------
    # Filter mesh with non-background values from a second (same-size) mesh:
    #-------------------------------------------------------------------------
    if mask_file:
        mask, name = read_scalars(mask_file, True, True)
        if not masked_output:
            masked_output = os.path.join(os.getcwd(), 'temp.vtk')
        file_to_plot = masked_output

        #---------------------------------------------------------------------
        # Remove nonmask-valued vertices:
        #---------------------------------------------------------------------
        if remove_nonmask:
            #-----------------------------------------------------------------
            # Load VTK files:
            #-----------------------------------------------------------------
            faces, lines, indices, points, npoints, scalars, scalar_names, \
            o1 = read_vtk(vtk_file, True, True)
            #-----------------------------------------------------------------
            # Find mask indices, remove nonmask faces, and reindex:
            #-----------------------------------------------------------------
            Imask = [i for i,x in enumerate(mask) if x != nonmask_value]
            mask_faces = remove_faces(faces, Imask)
            mask_faces, points, \
            original_indices = reindex_faces_points(mask_faces, points)
            #-----------------------------------------------------------------
            # Write VTK file with scalar values:
            #-----------------------------------------------------------------
            if np.ndim(scalars) == 1:
                scalar_type = type(scalars[0]).__name__
            elif np.ndim(scalars) == 2:
                scalar_type = type(scalars[0][0]).__name__
            else:
                print("Undefined scalar type!")
            write_vtk(file_to_plot, points, [], [], mask_faces,
                      scalars[original_indices].tolist(), scalar_names,
                      scalar_type=scalar_type)
        else:
            scalars, name = read_scalars(vtk_file, True, True)
            scalars[mask == nonmask_value] = nonmask_value
            rewrite_scalars(vtk_file, file_to_plot, scalars)
    else:
        file_to_plot = vtk_file

    #-------------------------------------------------------------------------
    # Display with vtkviewer.py:
    #-------------------------------------------------------------------------
    if program == 'vtkviewer':
        plot_surfaces(file_to_plot, use_colormap=use_colormap,
                      colormap_file=colormap_file)
    #-------------------------------------------------------------------------
    # Display with mayavi2:
    #-------------------------------------------------------------------------
    elif program == 'mayavi2':
        cmd = ["mayavi2", "-d", file_to_plot, "-m", "Surface", "&"]
        execute(cmd, 'os')
def spectrum_per_label(vtk_file, spectrum_size=10, exclude_labels=[-1],
                       normalization='area', area_file='',
                       largest_segment=True):
    """
    Compute Laplace-Beltrami spectrum per labeled region in a file.

    Parameters
    ----------
    vtk_file : string
        name of VTK surface mesh file containing index scalars (labels)
    spectrum_size : integer
        number of eigenvalues to be computed (the length of the spectrum)
    exclude_labels : list of integers
        labels to be excluded
    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
    area_file :  string
        name of VTK file with surface area scalar values
    largest_segment :  Boolean
        compute spectrum only for largest segment with a given label?

    Returns
    -------
    spectrum_lists : list of lists
        first eigenvalues for each label's Laplace-Beltrami spectrum
    label_list : list of integers
        list of unique labels for which spectra are obtained

    Examples
    --------
    >>> # Uncomment "if label==22:" below to run example:
    >>> # Spectrum for Twins-2-1 left postcentral (22) pial surface:
    >>> import os
    >>> from mindboggle.shapes.laplace_beltrami import spectrum_per_label
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> vtk_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 = [0]  #[-1]
    >>> largest_segment = True
    >>> spectrum_per_label(vtk_file, spectrum_size, exclude_labels, None,
    >>>                    area_file, largest_segment)
    ([[6.3469513010430304e-18,
       0.0005178862383467463,
       0.0017434911095630772,
       0.003667561767487686,
       0.005429017880363784,
       0.006309346984678924]],
     [22])

    """
    from mindboggle.utils.io_vtk import read_vtk, read_scalars
    from mindboggle.utils.mesh import remove_faces, reindex_faces_points
    from mindboggle.shapes.laplace_beltrami import fem_laplacian,\
        spectrum_of_largest

    # Read VTK surface mesh file:
    faces, u1, u2, points, u4, labels, u5, u6 = read_vtk(vtk_file)

    # Area file:
    if area_file:
        areas, u1 = read_scalars(area_file)
    else:
        areas = None

    # Loop through labeled regions:
    ulabels = []
    [ulabels.append(int(x)) for x in labels if x not in ulabels
     if x not in exclude_labels]
    label_list = []
    spectrum_lists = []
    for label in ulabels:
      #if label == 22:
      #  print("DEBUG: COMPUTE FOR ONLY ONE LABEL")

        # Determine the indices per label:
        Ilabel = [i for i,x in enumerate(labels) if x == label]
        print('{0} vertices for label {1}'.format(len(Ilabel), label))

        # Remove background faces:
        pick_faces = remove_faces(faces, Ilabel)
        pick_faces, pick_points, o1 = reindex_faces_points(pick_faces, points)

        # Compute Laplace-Beltrami spectrum for the label:
        if largest_segment:
            exclude_labels_inner = [-1]
            spectrum = spectrum_of_largest(pick_points, pick_faces,
                                           spectrum_size,
                                           exclude_labels_inner,
                                           normalization, areas)
        else:
            spectrum = fem_laplacian(pick_points, pick_faces,
                                     spectrum_size, normalization)

        # Append to a list of lists of spectra:
        spectrum_lists.append(spectrum)
        label_list.append(label)

    return spectrum_lists, label_list
Exemple #4
0
def explode_scalars(input_indices_vtk, input_values_vtk='', output_stem='',
                    exclude_values=[-1], background_value=-1,
                    output_scalar_name='scalars',
                    remove_background_faces=True, reindex=True):
    """
    Write out a separate VTK file for each integer (not in exclude_values)
    in (the first) scalar list of an input VTK file.
    Optionally write the values drawn from a second VTK file,
    remove background values, and reindex indices.

    Parameters
    ----------
    input_indices_vtk : string
        path of the input VTK file that contains indices as scalars
        (assumes that the scalars are a list of floats or integers)
    input_values_vtk : string
        path of the input VTK file that contains values as scalars
    output_stem : string
        path and stem of the output VTK file
    exclude_values : list or array
        values to exclude
    background_value : integer or float
        background value in output VTK files
    remove_background_faces : Boolean
        remove all faces whose three vertices are not all a given index?
    reindex : Boolean
        reindex all indices in faces?

    Examples
    --------
    >>> # Example 1:  explode sulci with thickness values
    >>> import os
    >>> from mindboggle.utils.io_vtk import explode_scalars
    >>> from mindboggle.utils.plots import plot_surfaces
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> input_indices_vtk = os.path.join(path, 'arno', 'features', 'sulci.vtk')
    >>> input_values_vtk = os.path.join(path, 'arno', 'shapes', 'lh.pial.travel_depth.vtk')
    >>> output_stem = 'sulci_depth'
    >>> #
    >>> explode_scalars(input_indices_vtk, input_values_vtk, output_stem)
    >>> #
    >>> # View:
    >>> example_vtk = os.path.join(os.getcwd(), output_stem + '0.vtk')
    >>> plot_surfaces(example_vtk)
    >>> #
    >>> # Example 2:  explode labels
    >>> import os
    >>> from mindboggle.utils.io_vtk import explode_scalars
    >>> from mindboggle.utils.plots import plot_surfaces
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> input_values_vtk = os.path.join(path, 'arno', 'labels',
    >>>                                 'lh.labels.DKT25.manual.vtk')
    >>> input_indices_vtk = input_values_vtk
    >>> output_stem = 'label'
    >>> exclude_values = [-1]
    >>> background_value = -1,
    >>> output_scalar_name = 'scalars'
    >>> remove_background_faces = True
    >>> reindex = True
    >>> #
    >>> explode_scalars(input_indices_vtk, input_values_vtk, output_stem,
    >>>                 exclude_values, background_value,
    >>>                 output_scalar_name, remove_background_faces, reindex)
    >>> # View:
    >>> example_vtk = os.path.join(os.getcwd(), output_stem + '2.vtk')
    >>> plot_surfaces(example_vtk)

    """
    import os
    import numpy as np
    from mindboggle.utils.io_vtk import read_scalars, read_vtk, write_vtk
    from mindboggle.utils.mesh import reindex_faces_points, remove_faces

    # Load VTK file:
    faces, lines, indices, points, npoints, scalars, scalar_names, \
        foo1 = read_vtk(input_indices_vtk, True, True)
    print("Explode the scalar list in {0}".
          format(os.path.basename(input_indices_vtk)))
    if input_values_vtk != input_indices_vtk:
        values, name = read_scalars(input_values_vtk, True, True)
        print("Explode the scalar list of values in {0} "
              "with the scalar list of indices in {1}".
              format(os.path.basename(input_values_vtk),
                     os.path.basename(input_indices_vtk)))
    else:
        values = np.copy(scalars)

    # Loop through unique (non-excluded) scalar values:
    unique_scalars = np.unique(scalars)
    if all(unique_scalars==np.round(unique_scalars)):
        unique_scalars = [int(x) for x in unique_scalars
                          if x not in exclude_values]
    else:
        unique_scalars = [x for x in unique_scalars
                          if x not in exclude_values]

    for scalar in unique_scalars:

        # Remove background (keep only faces with the scalar):
        if remove_background_faces:
            scalar_indices = [i for i,x in enumerate(scalars) if x == scalar]
            scalar_faces = remove_faces(faces, scalar_indices)
        else:
            scalar_faces = faces

        # Reindex:
        if reindex:
            scalar_faces, select_points, \
            o1 = reindex_faces_points(scalar_faces, points)
        else:
            select_points = points

        # Create array and indices for scalar value:
        if reindex:
            len_indices = len(select_points)
            select_values = scalar * np.ones(len_indices)
        else:
            select_values = np.copy(values)
            select_values[scalars != scalar] = background_value
            len_indices = len([i for i,x in enumerate(select_values)
                               if x != background_value])

        print("  Scalar {0}: {1} vertices".format(scalar, len_indices))

        # Write VTK file with scalar values (list of values):
        if np.ndim(select_values) == 1:
            scalar_type = type(select_values[0]).__name__
        elif np.ndim(select_values) == 2:
            scalar_type = type(select_values[0][0]).__name__
        else:
            print("Undefined scalar type!")
        output_vtk = os.path.join(os.getcwd(),
                                  output_stem + str(scalar) + '.vtk')
        write_vtk(output_vtk, select_points, indices, lines, scalar_faces,
                  select_values.tolist(), output_scalar_name,
                  scalar_type=scalar_type)
Exemple #5
0
def plot_mask_surface(vtk_file, mask_file='', nonmask_value=-1,
                      masked_output='', remove_nonmask=False,
                      program='vtkviewer',
                      use_colormap=False, colormap_file=''):
    """
    Use vtkviewer or mayavi2 to visualize VTK surface mesh data.

    If a mask_file is provided, a temporary masked file is saved,
    and it is this file that is viewed.

    If using vtkviewer, can optionally provide colormap file
    or set $COLORMAP environment variable.

    Parameters
    ----------
    vtk_file : string
        name of VTK surface mesh file
    mask_file : string
        name of VTK surface mesh file to mask vtk_file vertices
    nonmask_value : integer
        nonmask (usually background) value
    masked_output : string
        temporary masked output file name
    remove_nonmask : Boolean
        remove vertices that are not in mask? (otherwise assign nonmask_value)
    program : string {'vtkviewer', 'mayavi2'}
        program to visualize VTK file
    use_colormap : Boolean
        use Paraview-style XML colormap file set by $COLORMAP env variable?
    colormap_file : string
        use colormap in given file if use_colormap==True?  if empty and
        use_colormap==True, use file set by $COLORMAP environment variable

    Examples
    --------
    >>> import os
    >>> from mindboggle.utils.plots import plot_mask_surface
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> vtk_file = os.path.join(path, 'arno', 'labels', 'lh.labels.DKT31.manual.vtk')
    >>> mask_file = os.path.join(path, 'test_one_label.vtk')
    >>> nonmask_value = 0 #-1
    >>> masked_output = ''
    >>> remove_nonmask = True
    >>> program = 'vtkviewer'
    >>> use_colormap = True
    >>> colormap_file = '' #'/software/mindboggle_tools/colormap.xml'
    >>> plot_mask_surface(vtk_file, mask_file, nonmask_value, masked_output, remove_nonmask, program, use_colormap, colormap_file)

    """
    import os
    import numpy as np

    from mindboggle.utils.mesh import remove_faces, reindex_faces_points
    from mindboggle.utils.utils import execute
    from mindboggle.utils.plots import plot_surfaces
    from mindboggle.utils.io_vtk import read_scalars, rewrite_scalars, \
                                        read_vtk, write_vtk

    #-------------------------------------------------------------------------
    # Filter mesh with non-background values from a second (same-size) mesh:
    #-------------------------------------------------------------------------
    if mask_file:
        mask, name = read_scalars(mask_file, True, True)
        if not masked_output:
            masked_output = os.path.join(os.getcwd(), 'temp.vtk')
        file_to_plot = masked_output

        #---------------------------------------------------------------------
        # Remove nonmask-valued vertices:
        #---------------------------------------------------------------------
        if remove_nonmask:
            #-----------------------------------------------------------------
            # Load VTK files:
            #-----------------------------------------------------------------
            faces, lines, indices, points, npoints, scalars, scalar_names, \
            o1 = read_vtk(vtk_file, True, True)
            #-----------------------------------------------------------------
            # Find mask indices, remove nonmask faces, and reindex:
            #-----------------------------------------------------------------
            Imask = [i for i,x in enumerate(mask) if x != nonmask_value]
            mask_faces = remove_faces(faces, Imask)
            mask_faces, points, \
            original_indices = reindex_faces_points(mask_faces, points)
            #-----------------------------------------------------------------
            # Write VTK file with scalar values:
            #-----------------------------------------------------------------
            if np.ndim(scalars) == 1:
                scalar_type = type(scalars[0]).__name__
            elif np.ndim(scalars) == 2:
                scalar_type = type(scalars[0][0]).__name__
            else:
                print("Undefined scalar type!")
            write_vtk(file_to_plot, points, [], [], mask_faces,
                      scalars[original_indices].tolist(), scalar_names,
                      scalar_type=scalar_type)
        else:
            scalars, name = read_scalars(vtk_file, True, True)
            scalars[mask == nonmask_value] = nonmask_value
            rewrite_scalars(vtk_file, file_to_plot, scalars)
    else:
        file_to_plot = vtk_file

    #-------------------------------------------------------------------------
    # Display with vtkviewer.py:
    #-------------------------------------------------------------------------
    if program == 'vtkviewer':
        plot_surfaces(file_to_plot, use_colormap=use_colormap,
                      colormap_file=colormap_file)
    #-------------------------------------------------------------------------
    # Display with mayavi2:
    #-------------------------------------------------------------------------
    elif program == 'mayavi2':
        cmd = ["mayavi2", "-d", file_to_plot, "-m", "Surface", "&"]
        execute(cmd, 'os')
def spectrum_of_largest(points, faces, n_eigenvalues=6, 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
    n_eigenvalues : 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 n_eigenvalues eigenvalues for Laplace-Beltrami spectrum

    Examples
    --------
    >>> # Spectrum 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.laplace_beltrami import spectrum_of_largest
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> label_file = os.path.join(path, 'arno', 'labels', 'lh.labels.DKT25.manual.vtk')
    >>> area_file = os.path.join(path, 'arno', 'shapes', 'lh.pial.area.vtk')
    >>> n_eigenvalues = 6
    >>> exclude_labels = [0]  #[-1]
    >>> normalization = None
    >>> faces, lines, indices, points, foo1, labels, foo2, foo3 = read_vtk(label_file,
    >>>      return_first=True, return_array=True)
    >>> I2 = [i for i,x in enumerate(labels) if x==2] # cingulate
    >>> I22 = [i for i,x in enumerate(labels) if x==22] # postcentral
    >>> I2.extend(I22)
    >>> faces = remove_faces(faces, I2)
    >>> areas, u1 = read_scalars(area_file, True, True)
    >>> #
    >>> spectrum_of_largest(points, faces, n_eigenvalues, exclude_labels,
    >>>                     normalization, areas)
    >>> #
    >>> # View:
    >>> from mindboggle.utils.plots import plot_vtk
    >>> scalars = np.zeros(np.shape(labels))
    >>> scalars[I2] = 1
    >>> vtk_file = 'test_two_labels.vtk'
    >>> write_vtk(vtk_file, points, indices, lines, faces,
    >>>           scalars, scalar_names='scalars')
    >>> plot_vtk(vtk_file)
        Load "Labels" scalars from lh.labels.DKT25.manual.vtk
        Reduced 290134 to 29728 triangular faces
        Load "scalars" scalars from lh.pial.area.vtk
        2 segments
        Reduced 29728 to 14498 triangular faces
        Compute linear FEM Laplace-Beltrami spectrum
        [-8.764053090852845e-18,
         0.00028121452203987146,
         0.0010941205613292243,
         0.0017301461686759188,
         0.0034244633555606295,
         0.004280982704174599]

    """
    from scipy.sparse.linalg import eigsh, lobpcg
    import numpy as np

    from mindboggle.utils.mesh import find_neighbors, remove_faces, \
        reindex_faces_points
    from mindboggle.utils.segment import segment
    from mindboggle.shapes.laplace_beltrami import fem_laplacian

    # Areas:
    use_area = False
    if isinstance(areas, np.ndarray) and np.shape(areas):
        use_area = True
    elif isinstance(areas, list) and len(areas):
        areas = np.array(areas)
        use_area = True

    # Check to see if there are enough points:
    min_npoints = n_eigenvalues
    npoints = len(points) 
    if npoints < min_npoints or len(faces) < min_npoints:
        print("The input size {0} ({1} faces) should be much larger "
              "than n_eigenvalues {2}".
              format(npoints, len(faces), n_eigenvalues))
        return None
    else:

        #---------------------------------------------------------------------
        # Segment the indices into connected sets of indices:
        #---------------------------------------------------------------------
        # Construct neighbor lists:
        neighbor_lists = find_neighbors(faces, npoints)

        # Determine the indices:
        indices = [x for sublst in faces for x in sublst]

        # Segment:
        segments = segment(indices, neighbor_lists, min_region_size=1,
            seed_lists=[], keep_seeding=False, spread_within_labels=False,
            labels=[], label_lists=[], values=[], max_steps='', verbose=False)

        #---------------------------------------------------------------------
        # Select the largest segment (connected set of indices):
        #---------------------------------------------------------------------
        unique_segments = [x for x in np.unique(segments)
                           if x not in exclude_labels]
        if len(unique_segments) > 1:
            select_indices = []
            max_segment_area = 0
            for segment_number in unique_segments:
                segment_indices = [i for i,x in enumerate(segments)
                                   if x == segment_number]
                if use_area:
                    segment_area = np.sum(areas[segment_indices])
                else:
                    segment_area = len(segment_indices)
                if segment_area > max_segment_area:
                    select_indices = segment_indices
                    max_segment_area = len(select_indices)
            print('Maximum size of {0} segments: {1} vertices'.
                  format(len(unique_segments), len(select_indices)))

            #-----------------------------------------------------------------
            # Extract points and renumber faces for the selected indices:
            #-----------------------------------------------------------------
            faces = remove_faces(faces, select_indices)
        else:
            select_indices = indices

        # Alert if the number of indices is small:
        if len(select_indices) < min_npoints:
            print("The input size {0} is too small.".format(len(select_indices)))
            return None
        elif faces:

            #-----------------------------------------------------------------
            # Reindex indices in faces:
            #-----------------------------------------------------------------
            faces, points = reindex_faces_points(faces, points)

            #-----------------------------------------------------------------
            # Compute spectrum:
            #-----------------------------------------------------------------
            spectrum = fem_laplacian(points, faces, n_eigenvalues,
                                     normalization)

            return spectrum

        else:
            return None
def spectrum_per_label(vtk_file, spectrum_size=10, exclude_labels=[-1],
                       normalization='area', area_file='',
                       largest_segment=True):
    """
    Compute Laplace-Beltrami spectrum per labeled region in a file.

    Parameters
    ----------
    vtk_file : string
        name of VTK surface mesh file containing index scalars (labels)
    spectrum_size : integer
        number of eigenvalues to be computed (the length of the spectrum)
    exclude_labels : list of integers
        labels to be excluded
    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
    area_file :  string
        name of VTK file with surface area scalar values
    largest_segment :  Boolean
        compute spectrum only for largest segment with a given label?

    Returns
    -------
    spectrum_lists : list of lists
        first eigenvalues for each label's Laplace-Beltrami spectrum
    label_list : list of integers
        list of unique labels for which spectra are obtained

    Examples
    --------
    >>> # Uncomment "if label==22:" below to run example:
    >>> # Spectrum for Twins-2-1 left postcentral (22) pial surface:
    >>> import os
    >>> from mindboggle.shapes.laplace_beltrami import spectrum_per_label
    >>> path = os.environ['MINDBOGGLE_DATA']
    >>> vtk_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 = [0]  #[-1]
    >>> largest_segment = True
    >>> spectrum_per_label(vtk_file, spectrum_size, exclude_labels, None,
    >>>                    area_file, largest_segment)
    ([[6.3469513010430304e-18,
       0.0005178862383467463,
       0.0017434911095630772,
       0.003667561767487686,
       0.005429017880363784,
       0.006309346984678924]],
     [22])

    """
    from mindboggle.utils.io_vtk import read_vtk, read_scalars
    from mindboggle.utils.mesh import remove_faces, reindex_faces_points
    from mindboggle.shapes.laplace_beltrami import fem_laplacian,\
        spectrum_of_largest

    # Read VTK surface mesh file:
    faces, u1, u2, points, u4, labels, u5, u6 = read_vtk(vtk_file)

    # Area file:
    if area_file:
        areas, u1 = read_scalars(area_file)
    else:
        areas = None

    # Loop through labeled regions:
    ulabels = []
    [ulabels.append(int(x)) for x in labels if x not in ulabels
     if x not in exclude_labels]
    label_list = []
    spectrum_lists = []
    for label in ulabels:
      #if label == 22:
      #  print("DEBUG: COMPUTE FOR ONLY ONE LABEL")

        # Determine the indices per label:
        Ilabel = [i for i,x in enumerate(labels) if x == label]
        print('{0} vertices for label {1}'.format(len(Ilabel), label))

        # Remove background faces:
        pick_faces = remove_faces(faces, Ilabel)
        pick_faces, pick_points, o1 = reindex_faces_points(pick_faces, points)

        # Compute Laplace-Beltrami spectrum for the label:
        if largest_segment:
            exclude_labels_inner = [-1]
            spectrum = spectrum_of_largest(pick_points, pick_faces,
                                           spectrum_size,
                                           exclude_labels_inner,
                                           normalization, areas)
        else:
            spectrum = fem_laplacian(pick_points, pick_faces,
                                     spectrum_size, normalization)

        # Append to a list of lists of spectra:
        spectrum_lists.append(spectrum)
        label_list.append(label)

    return spectrum_lists, label_list