def write_sopath2skeleton(so_path, dest_path, scaling=None, comment=None): """ Writes very simple skeleton, each node represents the center of mass of a SV, and edges are created in list order. Parameters ---------- so_path : list of SegmentationObject dest_path : str scaling : np.ndarray or tuple comment : str """ if scaling is None: scaling = np.array(global_params.config["Dataset"]["scaling"]) skel = Skeleton() anno = SkeletonAnnotation() anno.scaling = scaling rep_nodes = [] for so in so_path: vert = so.mesh[1].reshape((-1, 3)) com = np.mean(vert, axis=0) kd_tree = spatial.cKDTree(vert) dist, nn_ix = kd_tree.query([com]) nn = vert[nn_ix[0]] / scaling n = SkeletonNode().from_scratch(anno, nn[0], nn[1], nn[2]) anno.addNode(n) rep_nodes.append(n) for i in range(1, len(rep_nodes)): anno.addEdge(rep_nodes[i - 1], rep_nodes[i]) if comment is not None: anno.setComment(comment) skel.add_annotation(anno) skel.to_kzip(dest_path)
def nxGraph2kzip(g, coords, kzip_path): import tqdm scaling = global_params.config.entries['Dataset']['scaling']() coords = coords / scaling skel = Skeleton() anno = SkeletonAnnotation() anno.scaling = scaling node_mapping = {} pbar = tqdm.tqdm(total=len(coords) + len(g.edges())) for v in g.nodes(): c = coords[v] n = SkeletonNode().from_scratch(anno, c[0], c[1], c[2]) node_mapping[v] = n anno.addNode(n) pbar.update(1) for e in g.edges(): anno.addEdge(node_mapping[e[0]], node_mapping[e[1]]) pbar.update(1) skel.add_annotation(anno) skel.to_kzip(kzip_path) pbar.close()
def glia_path_length(glia_path, glia_dict, write_paths=None): """ Get the path length of glia SV within glia_path. Assumes single connected glia component within this path. Uses the mesh property of each SegmentationObject to build a graph from all vertices to find shortest path through (or more precise: along the surface of) glia. Edges between non-glia vertices have negligible distance (0.0001) to ensure shortest path along non-glia surfaces. Parameters ---------- glia_path : list of SegmentationObjects glia_dict : dict Dictionary which keys the SegmentationObjects in glia_path and returns their glia prediction write_paths : bool Returns ------- float Shortest path between neuron type nodes in nm """ g = nx.Graph() col = {} curr_ind = 0 if write_paths is not None: all_vert = np.zeros((0, 3)) for so in glia_path: is_glia_sv = int(glia_dict[so] > 0) ind, vert = so.mesh # connect meshes of different SV, starts after first SV if curr_ind > 0: # build kd tree from vertices of SV before kd_tree = spatial.cKDTree(vert_resh) # get indices of vertives of SV before (= indices of graph nodes) ind_offset_before = curr_ind - len(vert_resh) # query vertices of current mesh to find close connects next_vert_resh = vert.reshape((-1, 3)) dists, ixs = kd_tree.query(next_vert_resh, distance_upper_bound=500) for kk, ix in enumerate(ixs): if dists[kk] > 500: continue if is_glia_sv: edge_weight = eucl_dist(next_vert_resh[kk], vert_resh[ix]) else: edge_weight = 0.0001 g.add_edge(curr_ind + kk, ind_offset_before + ix, weights=edge_weight) vert_resh = vert.reshape((-1, 3)) # save all vertices for writing shortest path skeleton if write_paths is not None: all_vert = np.concatenate([all_vert, vert_resh]) # connect fragments of SV mesh kd_tree = spatial.cKDTree(vert_resh) dists, ixs = kd_tree.query(vert_resh, k=20, distance_upper_bound=500) for kk in range(len(ixs)): nn_ixs = ixs[kk] nn_dists = dists[kk] col[curr_ind + kk] = glia_dict[so] for curr_ix, curr_dist in zip(nn_ixs, nn_dists): col[curr_ind + curr_ix] = glia_dict[so] if is_glia_sv: dist = curr_dist else: # only take path through glia into account dist = 0 g.add_edge(kk + curr_ind, curr_ix + curr_ind, weights=dist) curr_ind += len(vert_resh) start_ix = 0 # choose any index of the first mesh end_ix = curr_ind - 1 # choose any index of the last mesh shortest_path_length = nx.dijkstra_path_length(g, start_ix, end_ix, weight="weights") if write_paths is not None: shortest_path = nx.dijkstra_path(g, start_ix, end_ix, weight="weights") anno = coordpath2anno([all_vert[ix] for ix in shortest_path]) anno.setComment("{0:.4}".format(shortest_path_length)) skel = Skeleton() skel.add_annotation(anno) skel.to_kzip("{{}/{0:.4}_vertpath.k.zip".format( write_paths, shortest_path_length)) return shortest_path_length