Exemplo n.º 1
0
def run_from_args(args):
    """
    Runs the script based on a Namespace containing the command line arguments
    """
    if (
            args.output_dist is None and
            args.output_closest_vertex is None and
            args.output_predecessor_vertex is None and
            args.project is None
    ):
        raise ValueError("No output files requested, set at least one of -p, -od, -orv, or -onv")
    surface = CorticalMesh.read(args.surface)
    roi = nib.load(args.roi).darrays[0].data != 0
    if args.project is not None:
        to_project = nib.load(args.project[0]).darrays[0].data
    distance, predecessor, closest_vertex = run(
            surface, roi
    )
    if args.output_dist is not None:
        write_gifti(args.output_dist, [distance], brain_structure=surface.anatomy)
    if args.output_closest_vertex is not None:
        write_gifti(args.output_closest_vertex, [closest_vertex], brain_structure=surface.anatomy)
    if args.output_predecessor_vertex is not None:
        write_gifti(args.output_predecessor_vertex, [predecessor], brain_structure=surface.anatomy)
    if args.project is not None:
        projected = to_project[closest_vertex]
        write_gifti(args.project[1], [projected], brain_structure=surface.anatomy)
Exemplo n.º 2
0
def read_fsaverage_surface():
    """
    Reads the left pial surface from the fsaverage directory
    """
    filename = os.path.join(fsaverage_directory,
                            '100000.L.pial.32k_fs_LR.surf.gii')
    return CorticalMesh.read(filename)
Exemplo n.º 3
0
def test_roi_dist_gifti():
    surf_fn = Path(fsaverage_directory) / '100000.L.white.32k_fs_LR.surf.gii'
    surface = CorticalMesh.read(surf_fn)
    roi = np.zeros(surface.nvertices, dtype='i4')
    roi[5] = 1
    tp = np.arange(surface.nvertices)**2
    dist, closest, pred, projected = run_roi_dist_gifti(surf_fn,
                                                        roi,
                                                        surface.anatomy,
                                                        project=tp)

    assert dist[5] == 0
    assert (dist[6:] > 0).all()
    assert (dist[:5] > 0).all()
    assert (closest == 5).all()
    assert pred[5] == -1
    assert (projected == 25).all()

    roi[50] = 1
    dist, closest, pred = run_roi_dist_gifti(surf_fn, roi, surface.anatomy)
    assert dist[5] == 0
    assert dist[50] == 0
    assert (dist[:5] > 0).all()
    assert (dist[6:50] > 0).all()
    assert (dist[51:] > 0).all()
    assert ((closest == 5) | (closest == 50)).all()
    assert ((projected == 25) | (projected == 2500)).all()
    assert closest[5] == 5
    assert closest[50] == 50
    assert pred[5] == -1
    assert pred[50] == -1
Exemplo n.º 4
0
def run(surface: CorticalMesh, roi: np.ndarray):
    """
    Finds the shortest route to the ROI for every vertex

    :param surface: cortical surface
    :param roi: region of interest
    :return:
    """
    graph = surface.graph_point_point('distance', dtype='float')
    roi_dist, roi_idx = sparse_min(graph[roi, :], 0)
    stack1 = sparse.vstack((roi_dist[~roi], graph[~roi, :][:, ~roi])).tocsr()
    full_mat = sparse.hstack((np.append(0, roi_dist[~roi])[:, None], stack1))

    dist_matrix, predecessors = csgraph.dijkstra(full_mat, indices=0, directed=False,
                                                 return_predecessors=True)
    full_dist_matrix = np.zeros(surface.nvertices)
    full_dist_matrix[~roi] = dist_matrix[1:]

    original_predecessors = np.zeros(predecessors.shape)
    original_idx = np.arange(surface.nvertices)
    original_predecessors[predecessors != 0] = original_idx[~roi][predecessors[predecessors != 0] - 1]

    original_predecessors[predecessors == 0] = original_idx[roi][roi_idx[predecessors[predecessors == 0] - 1]]
    full_predecessors = -np.ones(surface.nvertices, dtype='i4')
    full_predecessors[~roi] = original_predecessors[1:]

    closest_vertex = full_predecessors.copy()
    closest_vertex[roi] = original_idx[roi]
    for _ in range(surface.nvertices):
        replace = (~roi[closest_vertex]) & (closest_vertex != -1)
        if not replace.any():
            break
        closest_vertex[replace] = full_predecessors[closest_vertex[replace]]

    return full_dist_matrix, full_predecessors, closest_vertex
Exemplo n.º 5
0
def run_from_args(args):
    """
    Runs the script based on a Namespace containing the command line arguments
    """
    surface = CorticalMesh.read(args.surface)
    arr = nib.load(args.depth).darrays[0].data
    if args.flip:
        arr *= -1
    use = np.isfinite(arr) & (arr != 0)
    if args.Nparcels is not None:
        segments = run(
            surface[use],
            arr[use],
            min_depth=args.min_depth,
            min_size=args.min_size,
            fill_ridge=args.fill_ridge,
        )
    else:
        segments = run_nparcels(
            surface[use],
            arr[use],
            nparcels=args.Nparcels,
            min_size=args.min_size,
            fill_ridge=args.fill_ridge,
        )
    full_segment = np.zeros(arr.size, dtype='i4')
    full_segment[use] = segments
    write_gifti(args.out, [full_segment],
                color_map='default',
                brain_structure=surface.anatomy)
Exemplo n.º 6
0
def run(surface: CorticalMesh, sulcal_depth, to_extract, minimum=False):
    """
    Extracts values from the ridge
    """
    gradient = surface.gradient(sulcal_depth)
    if minimum:
        gradient *= -1
    return track.extract_ridge_values(surface, gradient.T, to_extract)
Exemplo n.º 7
0
def run_from_args(args):
    """
    Runs the script based on a Namespace containing the command line arguments
    """
    surface = CorticalMesh.read(args.surface)
    sulcal_depth = nib.load(args.sulcal_depth).darrays[0].data
    to_extract = nib.load(args.extract).darrays[0].data
    values = run(surface, sulcal_depth, to_extract, args.minimum)
    write_gifti(args.out, [values], surface.anatomy)
Exemplo n.º 8
0
def run_from_args(args):
    """
    Runs script from command line arguments

    :param args: command line arguments from :func:`add_to_parser`.
    """
    surf = CorticalMesh.read(args.input)
    mask = np.zeros(surf.nvertices, dtype=int)
    mask[list(args.index)] = 1
    surf.write(args.output, mask)
Exemplo n.º 9
0
def run(surface: CorticalMesh,
        depth,
        min_depth=0,
        min_size=0,
        fill_ridge=False):
    """
    Runs watershed on the graph generated on the surface

    :param surface: mesh representing cortical surface
    :param depth: (N, ) array where N is number of vertices
    :param min_depth: minimum offset between minimum along ridge and minimum depth for each segment
    :param min_size: minimal size of each segment in mm^2
    :param fill_ridge: if True, fills the ridge with the value of the smaller of the neighbouring parcels
    :return: (N, ) array with segmentation (-1 on edges, 1-M within segments, where M is the number of segments)
    """
    graph = surface.graph_point_point().tocsr()
    max_edges = graph.sum(-1).max()
    neighbours = -np.ones((surface.nvertices, max_edges), dtype='i4')
    sorting = np.argsort(depth)
    sorted_graph = graph[:, sorting][sorting, :]
    for idx in range(surface.nvertices):
        ptrs = sorted_graph.indptr[idx:]
        neighbours[idx, :ptrs[1] -
                   ptrs[0]] = sorted_graph.indices[ptrs[0]:ptrs[1]]

    segment = np.zeros(surface.nvertices, dtype='i4')
    _watershed(segment, neighbours, depth[sorting],
               np.zeros(surface.nvertices, dtype=depth.dtype), min_depth,
               surface.size_vertices()[sorting], np.zeros(surface.nvertices),
               min_size, fill_ridge)

    cleaned_segment = np.zeros(surface.nvertices, dtype='i4')
    cleaned_segment[segment >= 0] = np.unique(segment[segment >= 0],
                                              return_inverse=True)[1] + 1
    cleaned_segment[segment == -1] = -1
    cleaned_segment[segment == -2] = -2

    orig_segment = np.zeros(surface.nvertices, dtype='i4')
    orig_segment[sorting] = cleaned_segment
    logger.info(f'{np.unique(segment[segment > 0]).size} segments found')
    return orig_segment
Exemplo n.º 10
0
def mesh_to_cortex(mesh: Mesh2D, cortex='left') -> CorticalMesh:
    """
    Converts mesh to cortical surface by defining it as left or right cortex

    :param mesh: surface mesh
    :param cortex: 'left' or 'right', defining which cortex this should represent
    :return: same mesh but as a CorticalMesh
    """
    return CorticalMesh(mesh.vertices,
                        mesh.faces,
                        mesh.flip_normal,
                        anatomy=BrainStructure('cortex', hemisphere=cortex))
Exemplo n.º 11
0
def run_from_args(args):
    """
    Runs script from command line arguments

    :param args: command line arguments from :func:`add_to_parser`.
    """
    surf = CorticalMesh.read(args.input)
    if args.preserve_bumps:
        res = surf.smooth(args.nsteps, args.step)
    else:
        intermediate = surf.smooth(args.nsteps, args.step, expand_step=0)
        res = intermediate.inflate(volume=surf.volume() -
                                   intermediate.volume())
    res.write(args.output, **surf.anatomy.gifti)
Exemplo n.º 12
0
def run_from_args(args):
    """
    Runs the script based on a Namespace containing the command line arguments
    """
    surf = CorticalMesh.read(args.surface)
    go = GreyOrdinates.from_filename(args.features)
    features = go.surface(surf.anatomy)
    mask = np.isfinite(features)
    res = run(
        surf[mask],
        features,
        n_iter=args.iter,
        metric=args.metric,
        method=args.cluster,
    )
    full_res = np.zeros(surf.nvertices)
    full_res[mask] = res
    write_gifti(args.output, [full_res], surf.anatomy)
Exemplo n.º 13
0
def run_from_args(args):
    """
    Runs the script based on a Namespace containing the command line arguments
    """
    logger.info('starting %s', op.basename(__file__))
    mask = nib.load(args.mask).darrays[0].data > 0
    full_surface = CorticalMesh.read(args.surface)
    labels = run(
        surface=full_surface[mask],
        ncluster=args.ncluster,
        max_iter=args.iter,
    )
    full_labels = np.zeros(full_surface.nvertices, dtype='i4')
    full_labels[mask] = labels + 1

    write_gifti.write_gifti(args.out, [full_labels],
                            brain_structure=full_surface.anatomy,
                            color_map={0: ('unk', (0, 0, 0, 0))})
    logger.info('ending %s', op.basename(__file__))
Exemplo n.º 14
0
def run(surface: CorticalMesh, ncluster: int, max_iter=0):
    """
    Creates a random parcellation of the surface based on the distance between surface elements

    :param surface: cortical surface with N vertices
    :param ncluster: number of clusters
    :param max_iter: maximum number of iterations in the k-medoids (if 0 a fast voronoi evaluation is used)
    :return: (N, ) integer array with values from 0 to N-1
    """
    sparse_dist_map = surface.graph_point_point(weight='distance', dtype='f8')
    if max_iter == 0:
        centroids = uniform_centroids(sparse_dist_map, ncluster)
        dens_dist_map = csgraph.dijkstra(sparse_dist_map,
                                         indices=centroids,
                                         directed=False)
        return dens_dist_map.argmin(0)
    else:
        dense_dist_map = csgraph.dijkstra(sparse_dist_map, directed=False)
        return kmedoids.kmedoids(dense_dist_map, ncluster,
                                 max_loops=max_iter)[1]
Exemplo n.º 15
0
def run_from_args(args):
    """
    Runs the script based on a Namespace containing the command line arguments
    """
    surface = CorticalMesh.read(args.surface)
    go = GreyOrdinates.from_filename(args.features)
    features = go.surface(surface.anatomy)
    mask = np.isfinite(features)
    labels = run(
            surface[mask],
            features[..., mask],
            metric=args.metric,
            method=args.cluster,
            n_clusters=args.n_clusters,
    )
    full_labels = -np.ones(surface.nvertices, dtype=labels.dtype)
    full_labels[mask] = labels
    write_gifti(args.output, [full_labels],
                brain_structure=surface.anatomy,
                color_map={-1: ('???', (0, 0, 0, 0))})
Exemplo n.º 16
0
def run(surface: CorticalMesh,
        features,
        n_iter=20,
        metric='spearman',
        method='spectral'):
    """
    Repeatedly identify the border between clusters in a spotlight fashion

    :param surface: anatomical surface with N vertices
    :param features: (N, M) array of surface features
    :param n_iter: number of  iterations
    :param metric: which metric to use for the similarity between neighbouring vertices
    :param method: clustering method ('spectral', 'affinity', or 'DBSCAN')
    :return: (N, ) array with fraction of times a vertex was on the border between the clusters
    """
    sim_mat = gradient.distance(
        surface.graph_point_point(include_diagonal=False),
        features,
        metric=metric)
    on_border = np.zeros(surface.nvertices)
    for n_clusters in np.linspace(10, 100, n_iter):
        logger.info('Randomly parcellating cortex in %d clusters', n_clusters)
        parcellation = random.run(surface, int(n_clusters))
        logger.info('Running %s clustering on each cluster', method)
        for idx_cluster in range(int(n_clusters)):
            logger.debug('Processing cluster %d (out of %d)', idx_cluster,
                         int(n_clusters))
            mask = parcellation == idx_cluster
            labels = cluster.cluster(sim_mat[mask, :][:, mask],
                                     method=method,
                                     n_clusters=2)
            graph = surface[mask].graph_point_point()
            smooth_labels = (graph.dot(labels) +
                             labels) / (graph.dot(np.ones(mask.sum())) + 1)
            # edge detection only guaranteed to work properly for 2 clusters
            on_border[mask] += (smooth_labels % 1.) != 0.
    return on_border / n_iter