def collapse_soma_skeleton(soma_pt, verts, edges, soma_d_thresh=12000, mesh_to_skeleton_map=None): if soma_pt is not None: soma_pt_m = soma_pt[np.newaxis, :] dv = np.linalg.norm(verts - soma_pt_m, axis=1) soma_verts = np.where(dv < soma_d_thresh)[0] new_verts = np.vstack((verts, soma_pt_m)) soma_i = verts.shape[0] edges_m = edges.copy() edges_m[np.isin(edges, soma_verts)] = soma_i simple_verts, simple_edges = trimesh_vtk.remove_unused_verts( new_verts, edges_m) good_edges = ~(simple_edges[:, 0] == simple_edges[:, 1]) if mesh_to_skeleton_map is not None: new_mesh_to_skeleton_map = mesh_to_skeleton_map.copy() remap_rows = np.isin(mesh_to_skeleton_map, soma_verts) new_mesh_to_skeleton_map[remap_rows] = soma_i new_mesh_to_skeleton_map = utils.nanfilter_shapes( np.unique(edges_m.ravel()), new_mesh_to_skeleton_map) if mesh_to_skeleton_map is None: return simple_verts, simple_edges[good_edges] else: return simple_verts, simple_edges[ good_edges], new_mesh_to_skeleton_map else: simple_verts, simple_edges = trimesh_vtk.remove_unused_verts( verts, edges) return simple_verts, simple_edges
def collapse_soma_skeleton(soma_pt, verts, edges, soma_d_thresh=12000): if soma_pt is not None: soma_pt_m = soma_pt[np.newaxis, :] dv = np.linalg.norm(verts - soma_pt_m, axis=1) soma_verts = np.where(dv < soma_d_thresh)[0] new_verts = np.vstack((verts, soma_pt_m)) soma_i = verts.shape[0] edges[np.isin(edges, soma_verts)] = soma_i simple_verts, simple_edges = trimesh_vtk.remove_unused_verts( new_verts, edges) good_edges = ~(simple_edges[:, 0] == simple_edges[:, 1]) return simple_verts, simple_edges[good_edges] else: simple_verts, simple_edges = trimesh_vtk.remove_unused_verts( verts, edges) return simple_verts, simple_edges
def skeletonize(mesh_meta, seg_id, soma_pt=None, soma_thresh=7500, invalidation_d=10000, smooth_neighborhood=5, max_tip_d=2000, large_skel_path_threshold=5000, cc_vertex_thresh=100, do_cross_section=False): mesh = mesh_meta.mesh(seg_id=seg_id, merge_large_components=False, remove_duplicate_vertices=False) mesh.stitch_overlapped_components() all_paths, roots, tot_path_lengths = skeletonize_components( mesh, soma_pt=soma_pt, soma_thresh=soma_thresh, invalidation_d=invalidation_d, cc_vertex_thresh=cc_vertex_thresh) tot_edges = merge_tips(mesh, all_paths, roots, tot_path_lengths, large_skel_path_threshold=large_skel_path_threshold, max_tip_d=max_tip_d) skel_verts, skel_edges = trimesh_vtk.remove_unused_verts( mesh.vertices, tot_edges) smooth_verts = smooth_graph(skel_verts, skel_edges, neighborhood=smooth_neighborhood) if do_cross_section: cross_sections, centers = trimesh_vtk.calculate_cross_sections( mesh, smooth_verts, skel_edges) center_verts = recenter_verts(smooth_verts, skel_edges, centers) smooth_center_verts = smooth_graph(center_verts, skel_edges, neighborhood=smooth_neighborhood) return skel_verts, skel_edges, cross_sections, smooth_verts, smooth_center_verts else: return skel_verts, skel_edges, smooth_verts
def collapse_soma_skeleton(soma_pt, verts, edges, soma_d_thresh=12000, mesh_to_skeleton_map=None, soma_mesh_indices=None, return_filter=False, only_soma_component=True, return_soma_ind=False): """function to adjust skeleton result to move root to soma_pt Parameters ---------- soma_pt : numpy.array a 3 long vector of xyz locations of the soma (None to just remove duplicate ) verts : numpy.array a Nx3 array of xyz vertex locations edges : numpy.array a Kx2 array of edges of the skeleton soma_d_thresh : float distance from soma_pt to collapse skeleton nodes mesh_to_skeleton_map : np.array a M long array of how each mesh index maps to a skeleton vertex (default None). The function will update this as it collapses vertices to root. soma_mesh_indices : np.array a K long array of indices in the mesh that should be considered soma Any skeleton vertex on these vertices will all be collapsed to root. return_filter : bool whether to return a list of which skeleton vertices were used in the end for the reduced set of skeleton vertices only_soma_component : bool whether to collapse only the skeleton connected component which is closest to the soma_pt (default True) return_soma_ind : bool whether to return which skeleton index that is the soma_pt Returns ------- np.array verts, Px3 array of xyz skeleton vertices np.array edges, Qx2 array of skeleton edges (np.array) new_mesh_to_skeleton_map, returned if mesh_to_skeleton_map and soma_pt passed (np.array) used_vertices, if return_filter this contains the indices into the passed verts which the return verts is using int an index into the returned verts that is the root of the skeleton node, only returned if return_soma_ind is True """ if soma_pt is not None: if only_soma_component: closest_soma_ind = np.argmin( np.linalg.norm(verts - soma_pt, axis=1)) close_inds = np.linalg.norm(verts - soma_pt, axis=1) < soma_d_thresh orig_graph = utils.create_csgraph(verts, edges, euclidean_weight=False) speye = sparse.diags(close_inds.astype(int)) _, compids = sparse.csgraph.connected_components(orig_graph * speye) soma_verts = np.flatnonzero(compids[closest_soma_ind] == compids) else: dv = np.linalg.norm(verts - soma_pt_m, axis=1) soma_verts = np.where(dv < soma_d_thresh)[0] soma_pt_m = soma_pt[np.newaxis, :] new_verts = np.vstack((verts, soma_pt_m)) soma_i = verts.shape[0] edges_m = edges.copy() edges_m[np.isin(edges, soma_verts)] = soma_i simple_verts, simple_edges = trimesh_vtk.remove_unused_verts( new_verts, edges_m) good_edges = ~(simple_edges[:, 0] == simple_edges[:, 1]) if mesh_to_skeleton_map is not None: new_mesh_to_skeleton_map = mesh_to_skeleton_map.copy() remap_rows = np.isin(mesh_to_skeleton_map, soma_verts) new_mesh_to_skeleton_map[remap_rows] = soma_i new_mesh_to_skeleton_map = utils.nanfilter_shapes( np.unique(edges_m.ravel()), new_mesh_to_skeleton_map) if soma_mesh_indices is not None: new_mesh_to_skeleton_map[soma_mesh_indices] = len( simple_verts) - 1 output = [simple_verts, simple_edges[good_edges]] if mesh_to_skeleton_map is not None: output.append(new_mesh_to_skeleton_map) if return_filter: used_vertices = np.unique( edges_m.ravel())[: -1] #Remove the largest value which is soma_i output.append(used_vertices) if return_soma_ind: output.append(len(simple_verts) - 1) return output else: simple_verts, simple_edges = trimesh_vtk.remove_unused_verts( verts, edges) return simple_verts, simple_edges