Source code for ClearMap.Alignment.Stitching.layout_graph_utils

import numpy as np

try:
    import graph_tool as gt
    import graph_tool.topology as gtt
    graph_lib = 'graph_tool'
except ImportError:
    import igraph as gt
    graph_lib = 'igraph'


[docs] def get_graph(n_vertices, directed=False): g = gt.Graph(directed=directed) g.add_vertex(n_vertices) return g
[docs] def graph_to_connected_components(g): if graph_lib == 'graph_tool': connected_components, hist = gtt.label_components(g) connected_components = np.array(connected_components.a) n_components = len(hist) else: connected_components = g.clusters() _, n_components = np.unique(connected_components, return_counts=True) return connected_components, n_components
[docs] def get_connected_components(alignments, n_sources, source_to_index=None): """determine connected components""" g = get_graph(n_sources) if source_to_index is not None: for a in alignments: g.add_edge(source_to_index[a.pre], source_to_index[a.post]) else: for a in alignments: g.add_edge(a[0], a[1]) return graph_to_connected_components(g)
[docs] def connect_sources(alignments, n_sources, source_to_index): """construct minimal tree to connect sources""" graph = get_graph(n_sources, directed=True) if graph_lib == '': # FIXME: check name pos_tree = graph.new_edge_property('vector<int>') # FIXME: missing else: pos_tree = {} # An object indexable by edge should suffice for our purpose for a in alignments: i_pre = source_to_index[a.pre] i_post = source_to_index[a.post] e = graph.add_edge(i_pre, i_post) pos_tree[e] = a.displacement e = graph.add_edge(i_post, i_pre) pos_tree[e] = tuple(-s for s in a.displacement) # invert return graph, pos_tree
[docs] def get_positions_from_tree(g, fixed_source, source_to_index, n_sources, ndim, pos_tree): """calculate positions from tree""" start_id = 0 if fixed_source is not None: start_id = source_to_index[fixed_source] positions = np.zeros((n_sources, ndim), dtype=int) for i in range(n_sources): if graph_lib == 'graph_tool': _, edge_list = gtt.shortest_path(g, g.vertex(start_id), g.vertex(i)) else: edge_indices = g.get_shortest_paths(g.vs[3], g.vs[8], output='epath')[0] edge_list = [g.es[i] for i in edge_indices] for edge in edge_list: positions[i] += pos_tree[edge] return positions
[docs] def get_color_ids(sources, n_sources, color_ids): if color_ids is None: # find sources that overlap edges = [] for i, s in enumerate(sources): p1 = np.array(s.position, dtype=int) s1 = s.shape for j in range(i + 1, n_sources): p2 = np.array(sources[j].position, dtype=int) s2 = sources[j].shape if np.all(np.max([p1, p2], axis=0) < np.min([p1 + s1, p2 + s2], axis=0)): edges.append((i, j)) # find graph coloring of overlap structure g = get_graph(n_vertices=n_sources) if graph_lib == 'graph_tool': g.add_edge_list(edges) color_ids = np.array(gtt.sequential_vertex_coloring(g).a) # FIXME: missing else: g.add_edges(edges) color_ids = np.array(g.vertex_coloring_greedy()) return color_ids
[docs] def cluster_components(components): """Find the connected components of the cluster components""" c_lens = [len(c) for c in components] c_ids = np.cumsum(c_lens) c_ids = np.hstack([0, c_ids]) n_components = np.sum(c_lens) def is_to_c(s, i): return c_ids[s] + i def c_to_si(c): s = np.searchsorted(c_ids, c, side='right') - 1 i = c - c_ids[s] return s,i g = get_graph(n_components) for s in range(1, len(components)): for i, ci in enumerate(components[s - 1]): for j, cj in enumerate(components[s]): for c in ci: if c in cj: g.add_edge(is_to_c(s - 1, i), is_to_c(s, j)) break connected_components, n_components = graph_to_connected_components(g) components_full = [np.where(connected_components == i)[0] for i in range(n_components)] # remove isolated nodes components_full = [c for c in components_full if len(c) > 1] return components_full, is_to_c, c_to_si