def get_degree_of_separation_visualisation(self, author1, author2): if author1 == '' or author2 == '': return Graph() if author1 == author2: return Graph() # Compute all the shortest paths from author1 to author2 try: list_of_paths = all_shortest_paths(self.authors_graph, self.author_idx[author1], self.author_idx[author2]) except NetworkXError as e: return "Not found" g = Graph() # Add the shortest paths to the graph try: for path in list_of_paths: g.add_path(path) except NetworkXNoPath as e: return Graph() # Add attributes to nodes for i in g.nodes(): g.node[i]['name']=self.authors[i].name print g.nodes(data=True) return g
def find_communities(graph: networkx.Graph, logger=None) -> list: """ :param graph: a Graph instance from networkx :type graph: networkx.Graph :param logger: optional logger. A default null one will be created if none is provided. :type logger: (None|logging.Logger) This function is a wrapper around the networkX methods to find cliques and communities inside a graph. The method takes as input a precomputed graph and returns two lists: - cliques - communities """ if logger is None: logger = create_null_logger() logger.debug("Creating the communities for %s", logger.name) communities = [frozenset(comm) for comm in networkx.connected_components(graph)] logger.debug("Communities for %s:\n\t\t%s", logger.name, "\n\t\t".join( [str(_) for _ in communities])) # result = [frozenset(x) for x in communities.values()] for element in set.difference(set(graph.nodes()), set(chain(*communities[:]))): communities.append(frozenset([element])) return set(communities)
def test_maximal_cliques(self): """Test maximal_cliques.""" G = Graph() G.add_edge('b','c') G.add_edge('b','d') G.add_edge('b','e') G.add_edge('b','f') G.add_edge('b','a') G.add_edge('a','c') G.add_edge('a','d') G.add_edge('a','e') G.add_edge('c','d') G.add_edge('c','e') G.add_edge('c','f') G.add_edge('c','g') G.add_edge('d','e') G.add_edge('d','g') G.add_edge('e','g') G.add_edge('f','g') # A clique of 'a, b, c, d, e' and some other edges. nodes = G.nodes() S, H = pClique.convert_graph_connectivity_to_sparse(G, nodes) i = nodes.index('a') tQ = pClique.grasp(S, H, 1, 5, i) c = [nodes[i] for i in tQ] print c self.assertTrue(set(c) == set(['a', 'b', 'c', 'd', 'e']))
def polygon_skeleton(polygon, density=10): """ Given a buffer polygon, return a skeleton graph. """ skeleton = Graph() points = [] for ring in polygon_rings(polygon): points.extend(densify_line(list(ring.coords), density)) if len(points) <= 4: # don't bother with this one return skeleton print >> stderr, ' ', len(points), 'perimeter points', rbox = '\n'.join( ['2', str(len(points))] + ['%.2f %.2f' % (x, y) for (x, y) in points] + [''] ) qvoronoi = Popen('qvoronoi o'.split(), stdin=PIPE, stdout=PIPE) output, error = qvoronoi.communicate(rbox) voronoi_lines = output.splitlines() if qvoronoi.returncode: raise _QHullFailure('Failed with code %s' % qvoronoi.returncode) vert_count, poly_count = map(int, voronoi_lines[1].split()[:2]) for (index, line) in enumerate(voronoi_lines[2:2+vert_count]): point = Point(*map(float, line.split()[:2])) if point.within(polygon): skeleton.add_node(index, dict(point=point)) for line in voronoi_lines[2+vert_count:2+vert_count+poly_count]: indexes = map(int, line.split()[1:]) for (v, w) in zip(indexes, indexes[1:] + indexes[:1]): if v not in skeleton.node or w not in skeleton.node: continue v1, v2 = skeleton.node[v]['point'], skeleton.node[w]['point'] line = LineString([(v1.x, v1.y), (v2.x, v2.y)]) if line.within(polygon): skeleton.add_edge(v, w, dict(line=line, length=line.length)) removing = True while removing: removing = False for index in skeleton.nodes(): if skeleton.degree(index) == 1: depth = skeleton.node[index].get('depth', 0) if depth < 20: other = skeleton.neighbors(index)[0] skeleton.node[other]['depth'] = depth + skeleton.edge[index][other]['line'].length skeleton.remove_node(index) removing = True print >> stderr, 'contain', len(skeleton.edge), 'internal edges.' return skeleton
def make_colors(graph: nx.Graph) -> map: names = graph.nodes() longest = max(names) raw = [levenshtein_distance(x, longest) for x in names] largest_raw = max(raw) degrees = [graph.degree(x) for x in graph] largest_degrees = max(degrees) return map(lambda x, y: x + y, [int(10 * x/largest_degrees) for x in degrees], [10 * x/largest_raw for x in raw])
def polygon_dots_skeleton(polygon, points): ''' ''' skeleton = Graph() rbox = '\n'.join( ['2', str(len(points))] + ['%.2f %.2f' % (x, y) for (x, y) in points] + [''] ) qvoronoi = Popen('qvoronoi o'.split(), stdin=PIPE, stdout=PIPE) output, error = qvoronoi.communicate(rbox) voronoi_lines = output.splitlines() if qvoronoi.returncode: raise _QHullFailure('Failed with code %s' % qvoronoi.returncode) vert_count, poly_count = map(int, voronoi_lines[1].split()[:2]) for (index, line) in enumerate(voronoi_lines[2:2+vert_count]): point = Point(*map(float, line.split()[:2])) if point.within(polygon): skeleton.add_node(index, dict(point=point)) for line in voronoi_lines[2+vert_count:2+vert_count+poly_count]: indexes = map(int, line.split()[1:]) for (v, w) in zip(indexes, indexes[1:] + indexes[:1]): if v not in skeleton.node or w not in skeleton.node: continue v1, v2 = skeleton.node[v]['point'], skeleton.node[w]['point'] line = LineString([(v1.x, v1.y), (v2.x, v2.y)]) if line.within(polygon): skeleton.add_edge(v, w, dict(line=line, length=line.length)) removing = True while removing: removing = False for index in skeleton.nodes(): if skeleton.degree(index) == 1: depth = skeleton.node[index].get('depth', 0) if depth < 20: other = skeleton.neighbors(index)[0] skeleton.node[other]['depth'] = depth + skeleton.edge[index][other]['line'].length skeleton.remove_node(index) removing = True logging.debug('found %d skeleton edges' % len(skeleton.edge)) return skeleton
def build_clique_graph(graph: nx.Graph) -> nx.Graph: """ Builds a graph induced by `same_as` relationships. """ cliqueGraph = nx.Graph() with click.progressbar(graph.nodes(), label='building cliques') as bar: for n in bar: attr_dict = graph.node[n] if 'same_as' in attr_dict: for m in attr_dict['same_as']: cliqueGraph.add_edge(n, m, provided_by=attr_dict['provided_by']) for key, value in graph.node[n].items(): update(cliqueGraph.node[n], key, value) update(cliqueGraph.node[n], 'is_node', True) return cliqueGraph
def test_bad_input_vertex_position(self): graph = Graph() positions = [(1.0, 1.0), (1.5, 2.0), (1.0, 3.0), (2.0, 3.0), (3.0, 3.0), (2.0, 2.0)] [e1, e12, e2, e23, e3, e31] = self.create_nodes(graph, 1, 'E', positions) self.create_edges_chain(graph, [e1, e12, e2, e23, e3, e31, e1]) i = add_interior(graph, e1, e2, e3) with self.assertRaises(AssertionError): [i1, i3, i2a, i2b] = P5().apply(graph, [i]) self.assertEqual(len(graph.nodes()), 7) self.assertEqual(len(graph.edges()), 9) if self.showPlots: pyplot.title("Wrong vertex position", fontsize=16) visualize_graph_3d(graph) pyplot.show()
def _node_coords(g: nx.Graph, l: dict) -> Tuple: """Converts coordinates for the graph nodes for plotting purposes. Args: g (nx.Graph): input graph l (dict[int, float]): Dictionary of nodes and their respective coordinates. Can be generated using a NetworkX `layout <https://networkx.github.io/documentation/latest/ reference/drawing.html#module-networkx.drawing.layout>`__ Returns: dict[str, list]: lists of x and y coordinates accessed as keys of a dictionary """ n_x = [] n_y = [] for n in g.nodes(): n_x.append(l[n][0]) n_y.append(l[n][1]) return {"x": n_x, "y": n_y}
def quadratic_funding(G: nx.Graph, total_pot: float) -> dict: G = G.copy() grants = { label for label, node in G.nodes(data=True) if node["type"] == "grant" } M = nx.get_node_attributes(G, "match") total_match = sum(M.values()) F = {} if total_match > total_pot: F = {g: total_pot * M[g] / total_match for g in grants} else: if total_match == 0: total_match = 1.0 F = { g: M[g] + (1 + np.log(total_pot / total_match) / 100) for g in grants } return F
def _create_strtree(_graph: nx.Graph) -> strtree.STRtree: # create an STRtree points = [] for n, n_d in _graph.nodes(data=True): # x coordinate if 'x' not in _graph.nodes[n]: raise KeyError( f'Encountered node missing "x" coordinate attribute at node {n}.' ) x = _graph.nodes[n]['x'] # y coordinate if 'y' not in _graph.nodes[n]: raise KeyError( f'Encountered node missing "y" coordinate attribute at node {n}.' ) y = _graph.nodes[n]['y'] p = geometry.Point(x, y) p.uid = n points.append(p) return strtree.STRtree(points)
def simulate_inoculation(net: Graph, patient_zero: str, infection_probability: float, inoculator: str, inoculation_probability: float): """Simulate worm and inoculation propagation through a given network, from two given nodes. Returns the number of rounds to either fully infect or fully cure the network.""" infected = set(patient_zero) inoculated = set(inoculator) round_count = 0 print('Infecting ' + str(len(net.nodes())) + ' nodes, starting from ' + patient_zero + ', and inoculating from ' + inoculator + '.') while len(infected) > 0: currently_infected = len(infected) currently_inoculated = len(inoculated) new_infections = 0 if currently_infected > 0: for node in net.neighbors(choice(tuple(infected))): if node not in infected and node not in inoculated: if random() <= infection_probability: infected.add(node) new_infections += 1 for node in net.neighbors(choice(tuple(inoculated))): if node not in inoculated: if random() <= inoculation_probability: inoculated.add(node) if node in infected: infected.remove(node) for node in inoculated: if node in infected: infected.remove(node) round_count += 1 infection_delta = str(len(infected) - currently_infected) inoculation_delta = str(len(inoculated) - currently_inoculated) if not (infection_delta == '0' and inoculation_delta == '0'): print('Round: ' + str(round_count) + ', infection delta: ' + infection_delta + ' (' + str(new_infections) + ' new infections)' + ', inoculation delta: ' + inoculation_delta + ', total infected: ' + str(len(infected)) + ', total inoculated: ' + str(len(inoculated))) return round_count
def add_distance_threshold( G: nx.Graph, long_interaction_threshold: int, threshold: float = 5.0 ): """ Adds edges to any nodes within a given distance of each other. Long interaction threshold is used to specify minimum separation in sequence to add an edge between networkx nodes within the distance threshold :param G: Protein Structure graph to add distance edges to :type G: nx.Graph :param long_interaction_threshold: minimum distance in sequence for two nodes to be connected :type long_interaction_threshold: int :param threshold: Distance in angstroms, below which two nodes are connected :type threshold: float :return: Graph with distance-based edges added """ pdb_df = filter_dataframe( G.graph["pdb_df"], "node_id", list(G.nodes()), True ) dist_mat = compute_distmat(pdb_df) interacting_nodes = get_interacting_atoms(threshold, distmat=dist_mat) interacting_nodes = zip(interacting_nodes[0], interacting_nodes[1]) log.info(f"Found: {len(list(interacting_nodes))} distance edges") for a1, a2 in interacting_nodes: n1 = G.graph["pdb_df"].loc[a1, "node_id"] n2 = G.graph["pdb_df"].loc[a2, "node_id"] n1_chain = G.graph["pdb_df"].loc[a1, "chain_id"] n2_chain = G.graph["pdb_df"].loc[a2, "chain_id"] n1_position = G.graph["pdb_df"].loc[a1, "residue_number"] n2_position = G.graph["pdb_df"].loc[a2, "residue_number"] condition_1 = n1_chain != n2_chain condition_2 = ( abs(n1_position - n2_position) > long_interaction_threshold ) if condition_1 or condition_2: if G.has_edge(n1, n2): G.edges[n1, n2]["kind"].add("distance_threshold") else: G.add_edge(n1, n2, kind={"distance_threshold"})
def convert_nx_to_rdkit(graph: nx.Graph) -> 'Chem.Mol': """Convert a networkx graph to a RDKit Molecule Args: graph (nx.Graph) Graph format of the molecule Returns: (Chem.RWMol): Molecule to be converted """ mol = Chem.RWMol() # Special case: empty-graph if graph is None: return mol atomic_nums = nx.get_node_attributes(graph, 'atomic_num') chiral_tags = nx.get_node_attributes(graph, 'chiral_tag') formal_charges = nx.get_node_attributes(graph, 'formal_charge') node_is_aromatics = nx.get_node_attributes(graph, 'is_aromatic') node_hybridizations = nx.get_node_attributes(graph, 'hybridization') num_explicit_hss = nx.get_node_attributes(graph, 'num_explicit_hs') node_to_idx = {} for node in graph.nodes(): a = Chem.Atom(atomic_nums[node]) a.SetChiralTag(chiral_tags[node]) a.SetFormalCharge(formal_charges[node]) a.SetIsAromatic(node_is_aromatics[node]) a.SetHybridization(node_hybridizations[node]) a.SetNumExplicitHs(num_explicit_hss[node]) idx = mol.AddAtom(a) node_to_idx[node] = idx bond_types = nx.get_edge_attributes(graph, 'bond_type') for edge in graph.edges(): first, second = edge ifirst = node_to_idx[first] isecond = node_to_idx[second] bond_type = bond_types[first, second] mol.AddBond(ifirst, isecond, bond_type) Chem.SanitizeMol(mol) return mol
def quadratic_match(G: nx.Graph, threshold: float) -> dict: t1 = time() G = G.copy() raw_contributions = G.edges(data=True) grants_set = { n for n, attrs in G.nodes(data=True) if attrs["type"] == "grant" } contributions = [] for contrib in raw_contributions: amount = contrib[2]["amount"] grant = contrib[1] if grant not in grants_set: grant = contrib[0] contributor = contrib[1] else: contributor = contrib[0] # {'grant': {match, user, grant, amount}} element = {grant: (None, contributor, grant, amount)} contributions.append(element) contrib_dict = aggregate_contributions(contributions) pt_t1 = time() pair_totals = get_totals_by_pair(contrib_dict) pt_t2 = time() matches = { proj: match_project(contribz, pair_totals, threshold) for proj, contribz in contrib_dict.items() } pt_t3 = time() pair_totals_time = pt_t2 - pt_t1 match_vector_time = pt_t3 - pt_t2 t2 = time() total_time = t2 - t1 return { 'total_time': total_time, 'pair_totals_time': pair_totals_time, 'match_vector_time': match_vector_time }
def extract_subgraph_from_chains( g: nx.Graph, chains: List[str], filter_dataframe: bool = True, update_coords: bool = True, recompute_distmat: bool = False, inverse: bool = False, return_node_list: bool = False, ) -> Union[nx.Graph, List[str]]: """Extracts a subgraph from a graph based on a chain. :param g: The graph to extract the subgraph from. :type g: nx.Graph :param chain: The chain(s) to extract. :type chain: List[str] :param filter_dataframe: Whether to filter the pdb_df dataframe of the graph. Defaults to True. :type filter_dataframe: bool :param update_coords: Whether to update the coordinates of the graph. Defaults to True. :type update_coords: bool :param recompute_distmat: Whether to recompute the distance matrix of the graph. Defaults to False. :type recompute_distmat: bool :param inverse: Whether to inverse the selection. Defaults to False. :type inverse: bool :return: The subgraph or node list if return_node_list is True. :rtype: Union[nx.Graph, List[str]] """ node_list: List = [ n for n, d in g.nodes(data=True) if d["chain_id"] in chains ] node_list = list(set(node_list)) log.debug(f"Found {len(node_list)} nodes in the chain subgraph.") return extract_subgraph_from_node_list( g, node_list, filter_dataframe=filter_dataframe, update_coords=update_coords, recompute_distmat=recompute_distmat, inverse=inverse, return_node_list=return_node_list, )
def add_sidechain_vector(g: nx.Graph, scale: bool = True, reverse: bool = False): """Adds vector from node to average position of sidechain atoms. We compute the mean of the sidechain atoms for each node. For this we use the ``rgroup_df`` dataframe. If the graph does not contain the ``rgroup_df`` dataframe, we compute it from the ``raw_pdb_df``. If scale, we scale the vector to the unit vector. If reverse is True, we reverse the vector (``sidechain - node``). If reverse is false (default) we compute (``node - sidechain``). :param g: Graph to add vector to. :type g: nx.Graph :param scale: Scale vector to unit vector. Defaults to ``True``. :type scale: bool :param reverse: Reverse vector. Defaults to ``False``. :type reverse: bool """ # Get or compute R-Group DF if "rgroup_df" not in g.graph.keys(): g.graph["rgroup_df"] = compute_rgroup_dataframe(g.graph["raw_pdb_df"]) sc_centroid = g.graph["rgroup_df"].groupby("node_id").mean() # Iterate over nodes and compute vector for n, d in g.nodes(data=True): if d["residue_name"] == "GLY": # If GLY, set vector to 0 vec = np.array([0, 0, 0]) else: if reverse: vec = d["coords"] - np.array( sc_centroid.loc[n][["x_coord", "y_coord", "z_coord"]]) else: vec = (np.array( sc_centroid.loc[n][["x_coord", "y_coord", "z_coord"]]) - d["coords"]) if scale: vec = vec / np.linalg.norm(vec) d["sidechain_vector"] = vec
def atoms_neighborhoods_charges( graph: nx.Graph, nauty: Nauty, shell: int, atom_type_key: str) -> Generator[Tuple[Atom, str, float], None, None]: """Yields neighborhood hash and partial charge for each atom. Args: nauty: The Nauty instance to use to canonize the neighborhoods. shell: The shell size to use to make the neighborhood atom_type_key: The name of the atom type attribute to use Yields: Tuples containing an atom, the neighborhood hash, and the \ partial charge of the atom. """ for atom in graph.nodes(): if 'partial_charge' not in graph.node[atom]: raise KeyError( 'Missing property "partial_charge" for atom {}'.format(atom)) partial_charge = graph.node[atom]['partial_charge'] key = nauty.canonize_neighborhood(graph, atom, shell, atom_type_key) yield atom, key, partial_charge
def __init__(self, graph: Graph, start: int = 1): super().__init__() self.start: int = start self.nodes: List[int] = [self.start] self.cost: float = 0 self.tau_0: float = 0 n = len(graph) current = self.start unvisited = [x for x in graph.nodes() if x != self.start] while unvisited: costs = [graph.edges[current, x]['weight'] for x in unvisited] index = np.argmin(costs) self.cost += np.min(costs) current = unvisited[index] del unvisited[index] self.cost += graph.edges[current, self.start]['weight'] self.tau_0 = 1 / (n * self.cost) for u, v in graph.edges: graph.edges[u, v].setdefault('pheromone', self.tau_0)
def rotate_right_to_right(graph: nx.Graph) -> None: """Rotate the graph so that the partisan_retweet:right nodes are to the right. Assign the rotated positions to the graph nodes. """ partisan = nx.get_node_attributes(graph, 'partisan_retweet') right_nodes = list(filter(lambda n: partisan[n] == 'right', graph.nodes())) positions = nx.get_node_attributes(graph, 'position') best_rotation = 0 max_sum_x = 0 for rotation in range(0, 350, 10): rotated_positions = {n: rotate(x=positions[n][0], y=positions[n][1], d=rotation) for n in right_nodes} sum_x = sum([p[0] for p in rotated_positions.values()]) if sum_x > max_sum_x: max_sum_x = sum_x best_rotation = rotation for n in graph.nodes: graph.nodes[n]['position'] = rotate(x=positions[n][0], y=positions[n][1], d=best_rotation)
def plot_original(G: nx.Graph, out_name) -> None: pos_dot = nx.nx_agraph.graphviz_layout(G, prog="dot") pos_twopi = nx.nx_agraph.graphviz_layout(G, prog="twopi") color_map = [] for node in G.nodes(data=True): if node[1]['type'] == 'T': color_map.append('red') if node[1]['type'] == 'M': color_map.append('orange') if node[1]['type'] == 'CP': color_map.append('yellow') if node[1]['type'] == 'C': color_map.append('purple') plt.figure(3, figsize=(12, 12)) nx.draw(G, pos=pos_dot, node_size=150, node_color=color_map, width=0.5) plt.savefig(out_name + "_dot.pdf", format="pdf") plt.close() plt.figure(3, figsize=(12, 12)) nx.draw(G, pos=pos_twopi, node_size=150, node_color=color_map, width=0.5) plt.savefig(out_name + "_twopi.pdf", format="pdf") plt.close()
def get_unconnected_pairs(G: nx.Graph): # TODO: convert to sparse matrix node_list = list(G.nodes()) adj_G = nx.adj_matrix(G) # get unconnected node-pairs all_unconnected_pairs = [] # traverse adjacency matrix. find all unconnected node with maximum 2nd order offset = 0 for i in tqdm(range(adj_G.shape[0])): for j in range(offset, adj_G.shape[1]): if i != j: if nx.shortest_path_length(G, i, j) <= 2: if adj_G[i, j] == 0: all_unconnected_pairs.append( [node_list[i], node_list[j]]) offset = offset + 1 return all_unconnected_pairs
def draw_available_subgraph(G: nx.Graph, s: int, t: int, remove_rest: bool = False, pos=None): """ Draw available subgraph of G for path from s to t. :param G: graph :param s: source node :param t: target node :param remove_rest: if True draw whole G graph with marked subgraph, otherwise draw only subgraph :param pos: nodes position :return: """ if pos is None: pos = nx.spring_layout(G) H = available_subgraph(G, s, t) if remove_rest: draw_weighted_graph(H, pos) else: nodes_colors = ['red' if H.has_node(v) else 'green' for v in G.nodes()] edges_color = ['red' if H.has_edge(e[0], e[1]) else 'black' for e in G.edges()] nx.draw(G, pos=pos, with_labels=True, edge_color=edges_color, node_color=nodes_colors) nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=nx.get_edge_attributes(G, 'throughput')) return pos
def adjust_dfs_to_graph( df_train: pd.DataFrame, df_val: pd.DataFrame, df_test: pd.DataFrame, G: nx.Graph, column_to_predict: str, ) -> T.Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]: # We remove the users' rows who didn't rate `item_to_predict` df_train_adjusted = df_train.dropna(subset=[column_to_predict], axis="rows") df_val_adjusted = df_val.dropna(subset=[column_to_predict], axis="rows") df_test_adjusted = df_test.dropna(subset=[column_to_predict], axis="rows") # We remove those beers which were left out of the graph G beers_in_G = list(G.nodes()) df_train_adjusted = df_train_adjusted[beers_in_G] df_val_adjusted = df_val_adjusted[beers_in_G] df_test_adjusted = df_test_adjusted[beers_in_G] return (df_train_adjusted, df_val_adjusted, df_test_adjusted)
def persona_graph( G: nx.Graph, clustering: Callable[ [nx.Graph], Iterable[Sequence[Hashable]]] = nx.connected_components, ) -> nx.Graph: """ Construct the persona graph of a graph G, this preserves any edge attributes. :param G: input graph :param clustering: algorithm to cluster node on a graph, a callable taking a graph to an iterable of hashable sequences :return: persona graph """ # TODO preserve node data edge_remap = {} for n in G.nodes(): _, persona_remap = create_personas(G, n, clustering) edge_remap[n] = persona_remap persona_graph_edges = [(edge_remap[start][end], edge_remap[end][start], data) for start, end, data in G.edges(data=True)] return nx.from_edgelist(persona_graph_edges)
def nx_to_gdf(g: nx.Graph, nodes: bool = True, edges: bool = True) -> \ Union[gpd.GeoDataFrame, Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame]]: """ Converts a networkx Graph to a GeoDataFrame. :param nx.Graph g: networkx Graph. :param bool nodes: return a Point GeoDataFrame, derived from the network Graph nodes, default True. :param bool edges: return a LineString GeoDataFrame, derived from the network Graph edges, default True. :return Union[gpd.GeoDataFrame, Tuple[gpd.GeoDataFrame, gpd.GeoDataFrame]]: a Point GeoDataFrame and / or LineString GeoDataFrame, derived from the networkx Graph nodes and / or edges, respectively. """ logger.info("Loading NetworkX graph into GeoPandas GeoDataFrame.") # Generate GeoDataFrames for both networkx nodes and edges. gdf_nodes, gdf_edges = None, None # Compile node geometry and attributes. if nodes: node_xy, node_data = zip(*g.nodes(data=True)) gdf_nodes = gpd.GeoDataFrame( list(node_data), geometry=[Point(i, j) for i, j in node_xy]) gdf_nodes.crs = g.graph['crs'] # Compile edge geometry and attributes. if edges: starts, ends, edge_data = zip(*g.edges(data=True)) gdf_edges = gpd.GeoDataFrame(list(edge_data)) gdf_edges.crs = g.graph['crs'] logger.info( "Successfully loaded GeoPandas GeoDataFrame into NetworkX graph.") # Conditionally return nodes and / or edges. if all([nodes, edges]): return gdf_nodes, gdf_edges elif nodes is True: return gdf_nodes else: return gdf_edges
def qubo_circuit(graph: nx.Graph, steps: int, beta: Sequence, gamma: Sequence) -> Circuit: """ A QAOA circuit for the Quadratic Unconstrained Binary Optimization problem (i.e. an Ising model). Args: graph : a networkx graph instance with optional edge and node weights steps : number of QAOA steps beta : driver parameters (One per step) gamma : cost parameters (One per step) """ qubits = list(graph.nodes()) # Initialization circ = Circuit() for q0 in qubits: circ += H(q0) # Run for given number of QAOA steps for p in range(0, steps): # Cost for q0, q1 in graph.edges(): weight = graph[q0][q1].get('weight', 1.0) # Note factor of pi due to parameterization of ZZ gate circ += ZZ(-weight * gamma[p] / np.pi, q0, q1) for q0 in qubits: node_weight = graph.nodes[q0].get('weight', None) if node_weight is not None: circ += RZ(node_weight, q0) # Drive for q0 in qubits: circ += RX(beta[p], q0) return circ
def to_dataframe(G: nx.Graph, properties = tuple()): # Error check valid_properties = ('betweenness', 'eigenvector centrality', 'degree', 'in-degree', 'out-degree') for property in properties: if property not in valid_properties: raise Exception('Invalid property: "' + property + '"') # --- data_frame = pd.DataFrame.from_dict(dict(G.nodes(data=True)), orient='index') for property in properties: if property == 'betweenness': data_frame[property] = \ w.graph.betweenness(G) if property == 'degree': data_frame[property] = \ w.graph.degrees(G) if property == 'eigenvector centrality': data_frame[property] = \ w.graph.eigenvector_centrality(G) elif property == 'in-degree': data_frame[property] = \ w.graph.degrees(G, direction='in') elif property == 'out-degree': data_frame[property] = \ w.graph.degrees(G, direction='out') return data_frame
def add_beta_carbon_vector(g: nx.Graph, scale: bool = True, reverse: bool = False): """Adds vector from node (typically alpha carbon) to position of beta carbon. Glycine does not have a beta carbon, so we set it to ``np.array([0, 0, 0])``. We extract the position of the beta carbon from the unprocessed atomic PDB dataframe. For this we use the ``raw_pdb_df`` dataframe. If scale, we scale the vector to the unit vector. If reverse is True, we reverse the vector (``C beta - node``). If reverse is false (default) we compute (``node - C beta``). :param g: Graph to add vector to. :type g: nx.Graph :param scale: Scale vector to unit vector. Defaults to ``True``. :type scale: bool :param reverse: Reverse vector. Defaults to ``False``. :type reverse: bool """ c_beta_coords = filter_dataframe(g.graph["raw_pdb_df"], "atom_name", ["CB"], boolean=True) c_beta_coords.index = c_beta_coords["node_id"] # Iterate over nodes and compute vector for n, d in g.nodes(data=True): if d["residue_name"] == "GLY": vec = np.array([0, 0, 0]) else: if reverse: vec = d["coords"] - np.array( c_beta_coords.loc[n][["x_coord", "y_coord", "z_coord"]]) else: vec = (np.array( c_beta_coords.loc[n][["x_coord", "y_coord", "z_coord"]]) - d["coords"]) if scale: vec = vec / np.linalg.norm(vec) d["c_beta_vector"] = vec
def _make_nodes(self, source_graph: nx.Graph) -> None: logger.info("Grouping Nodes by type") # Group nodes by class sorted_nodes = sorted( [node["data"] for _, node in source_graph.nodes(data=True)], key=lambda node: node.__name__, reverse=True, ) nodes_by_type = itertools.groupby(sorted_nodes, key=lambda node: node.__name__) for node_type, nodes in nodes_by_type: # remove whitespaces node_type = node_type.replace(" ", "_") self._create_constraint(node_type) cypher_nodes = list(map(self._node_as_cypher, nodes)) logger.debug( f"Inserting {len(cypher_nodes)} {node_type} nodes into Neo4J") for i in range(0, len(cypher_nodes), self.batch_size): start = i end = i + self.batch_size cypher = f"UNWIND [{', '.join(cypher_nodes[start: end])}] as row\n" cypher += f"CREATE (node:{node_type} {{_key: row._key}}) SET node = row" with self.neo4j.session() as session: session.write_transaction(lambda tx: tx.run(cypher)) logger.debug(f"Finished batch {i+1} ({start} -> {end})")
def add_graph(self, graph: nx.Graph) -> None: """Draws nodes and edges from graph onto the given canvas :param graph: graph whose nodes and edges will be drawn :return: None """ for node in graph.nodes(): x = graph.nodes[node]['x'] y = graph.nodes[node]['y'] r = graph.nodes[node]['r'] degree = min(graph.degree(node), len(COLORS) - 1) # always draw degree 0, as it is not visible in 'edge only' mode if not self.draw_nodes and degree > 0: continue cid = graph.nodes[node].get('cluster', 0) # 0 means no cluster assigned ctag = 'c{}'.format(cid) ntag = 'n{}'.format(node) tags = ('Node', ntag,) if cid != 0: tags += (ctag, ) draw_id = self.canvas.create_oval(x - r, y - r, x + r, y + r, outline=COLORS[degree], width=2, activefill='turquoise1', tags=tags) self.canvas.tag_bind(draw_id, '<ButtonPress-1>', lambda event, cid=cid: self.highlight(cid)) dash = (4, 1) if self.draw_nodes else None for n1, n2 in graph.edges: n1_x = graph.nodes[n1]['x'] n1_y = graph.nodes[n1]['y'] n2_x = graph.nodes[n2]['x'] n2_y = graph.nodes[n2]['y'] self.canvas.create_line(n1_x, n1_y, n2_x, n2_y, dash=dash)
def hits_in_blob(track_graph: Graph, radius: float, extreme: Voxel) -> Sequence[BHit]: """Returns the hits that belong to a blob.""" distances = shortest_paths(track_graph) dist_from_extreme = distances[extreme] blob_pos = blob_centre(extreme) diag = np.linalg.norm(extreme.size) blob_hits = [] # First, consider only voxels at a certain distance from the end-point, along the track. # We allow for 1 extra contiguity, because this distance is calculated between # the centres of the voxels, and not the hits. In the second step we will refine the # selection, using the euclidean distance between the blob position and the hits. for v in track_graph.nodes(): voxel_distance = dist_from_extreme[v] if voxel_distance < radius + diag: for h in v.hits: hit_distance = np.linalg.norm(blob_pos - h.pos) if hit_distance < radius: blob_hits.append(h) return blob_hits
def subset_by_node_feature_value( G: nx.Graph, feature_name: str, feature_value: Any ) -> nx.Graph: """ Extracts a subgraph from a protein structure graph based on nodes with a certain feature value :param G: nx.Graph protein structure graph to extract a subgraph from :type G: nx.Graph :param feature_name: Name of feature to base subgraph extraction from :type feature_name: str :param feature_value: Value of feature to select :type feature_value: Any :return: Subgraph of G based on nodes with a given feature value :rtype: nx.Graph """ node_list = [] for n, d in G.nodes(data=True): if d[feature_name] == feature_value: node_list.append(n) return G.subgraph(node_list)
def make_random_walks(G: nx.Graph, num_walk, length_of_walk) -> List[List[str]]: # ランダムウォークで歩いたノードを入れるlistを生成 paths = list() # ランダムウォークを擬似的に行う for i in range(num_walk): node_list = list(G.nodes()) for node in node_list: now_node = node # 到達したノードを追加する用のリストを用意する path = list() path.append(str(now_node)) for j in range(length_of_walk): # 次に到達するノードを選択する next_node = random.choice(list(G.neighbors(now_node))) # リストに到達したノードをリストに追加する path.append(str(next_node)) # 今いるノードを「現在地」とする now_node = next_node # ランダムウォークしたノードをリストに追加 paths.append(path) # 訪れたノード群を返す return paths
def analyze_graph(graph: nx.Graph): """check the graph we have built is well-formed: ideally you have 4 corners, not less, edges count is a multiple of 4, and insiders count is the square of edges_count/4. (If not, good luck to you, I cannot help.) """ print(f"{len(graph)} tiles total") counts = {i: 0 for i in range(2, 5)} for n in graph.nodes(): neighbors_count = len(list(nx.neighbors(graph, n))) counts[neighbors_count] += 1 corners = counts[2] edges = counts[3] insiders = counts[4] print(f"-> {corners} corners") print(f"-> {edges} edges") print(f"-> {insiders} insiders") if corners != 4 or edges % 4 > 0 or (edges / 4) ** 2 != insiders: print(f"{u.RED}Your graph is pourri!{u.NORMAL}") else: print(f"{u.GREEN}Your graph is OK!{u.NORMAL}")
def _compute_ricci_curvature(G: nx.Graph, weight="weight", **kwargs): """Compute Ricci curvature of edges and nodes. The node Ricci curvature is defined as the average of node's adjacency edges. Parameters ---------- G : NetworkX graph A given directional or undirectional NetworkX graph. weight : str The edge weight used to compute Ricci curvature. (Default value = "weight") **kwargs Additional keyword arguments passed to `_compute_ricci_curvature_edges`. Returns ------- G: NetworkX graph A NetworkX graph with "ricciCurvature" on nodes and edges. """ # compute Ricci curvature for all edges edge_ricci = _compute_ricci_curvature_edges(G, weight=weight, **kwargs) # Assign edge Ricci curvature from result to graph G nx.set_edge_attributes(G, edge_ricci, "ricciCurvature") # Compute node Ricci curvature for n in G.nodes(): rc_sum = 0 # sum of the neighbor Ricci curvature if G.degree(n) != 0: for nbr in G.neighbors(n): if 'ricciCurvature' in G[n][nbr]: rc_sum += G[n][nbr]['ricciCurvature'] # Assign the node Ricci curvature to be the average of node's adjacency edges G.nodes[n]['ricciCurvature'] = rc_sum / G.degree(n) logger.debug("node %s, Ricci Curvature = %f" % (n, G.nodes[n]['ricciCurvature'])) return G
def _get_fbvs(self, graph: Graph): # get the list of cycles cycles = cycle_basis(graph) # if the graph is already acyclic, there's nothing to remove, so return an empty set if len(cycles) == 0: return set() # get the set of nodes that is in at least one cycle nodes_in_cycles = set([item for sublist in cycles for item in sublist]) min_num_to_remove = sys.maxsize min_nodes_to_remove = set() for node in nodes_in_cycles: # make an induced subgraph with the current node removed nodes = graph.nodes() nodes.remove(node) nodes_set = frozenset(nodes) if nodes_set in self.cacheDict: # if we have previously calculated the min fbvs for this induced subgraph, get that # fbvs from the cache dict nodes_to_remove = self.cacheDict[nodes_set] else: # otherwise we have to calculate it new_graph = graph.subgraph(nodes) nodes_to_remove = self._get_fbvs(new_graph) # add the newly calculated fbvs to the cache dict self.cacheDict[nodes_set] = nodes_to_remove if len(nodes_to_remove) < min_num_to_remove: min_num_to_remove = len(nodes_to_remove) nodes_to_remove.add(node) min_nodes_to_remove = nodes_to_remove return min_nodes_to_remove
class SimpleSectorNetworkCase(unittest.TestCase): def setUp(self): self.G = Graph() self.G.add_node(0, coord=(0., 0.)) self.G.add_node(1, coord=(1., 0.)) self.G.add_node(2, coord=(-0.5, np.sqrt(3.)/2.)) self.G.add_node(3, coord=(0.5, np.sqrt(3.)/2.)) self.G.add_node(4, coord=(1.5, np.sqrt(3.)/2.)) self.G.add_node(5, coord=(0., np.sqrt(3.))) self.G.add_node(6, coord=(1., np.sqrt(3.))) def show_network(self, show=True): plt.scatter(*zip(*[self.G.node[n]['coord'] for n in self.G.nodes()]), marker='s', color='r', s=50) if show: plt.show() def show_polygons(self, show=True): for pol in self.G.polygons.values(): plt.fill(*zip(*list(pol.exterior.coords)), alpha=0.4) if show: plt.show()
class Topo(object): "Data center network representation for structured multi-trees." def __init__(self, hopts=None, sopts=None, lopts=None, ropts=None): """Topo object: hinfo: default host options sopts: default switch options lopts: default link options""" self.g = Graph() self.node_info = {} self.link_info = {} # (src, dst) tuples hash to EdgeInfo objects self.hopts = {} if hopts is None else hopts self.ropts = {} if ropts is None else ropts self.sopts = {} if sopts is None else sopts self.lopts = {} if lopts is None else lopts self.ports = {} # ports[src][dst] is port on src that connects to dst def addNode(self, name, **opts): """Add Node to graph. name: name opts: node options returns: node name""" self.g.add_node(name) self.node_info[name] = opts return name def addHost(self, name, **opts): """Convenience method: Add host to graph. name: host name opts: host options returns: host name""" if not opts: if self.hopts: opts = self.hopts elif self.ropts: opts = self.ropts return self.addNode(name, **opts) def addSwitch(self, name, **opts): """Convenience method: Add switch to graph. name: switch name opts: switch options returns: switch name""" if not opts and self.sopts: opts = self.sopts result = self.addNode(name, isSwitch=True, **opts) return result def addLink(self, node1, node2, port1=None, port2=None, **opts): """node1, node2: nodes to link together port1, port2: ports (optional) opts: link options (optional) returns: link info key""" if not opts and self.lopts: opts = self.lopts self.addPort(node1, node2, port1, port2) key = tuple(self.sorted([node1, node2])) self.link_info[key] = opts self.g.add_edge(*key) return key def addPort(self, src, dst, sport=None, dport=None): '''Generate port mapping for new edge. @param src source switch name @param dst destination switch name ''' self.ports.setdefault(src, {}) self.ports.setdefault(dst, {}) # New port: number of outlinks + base src_base = 1 if self.isSwitch(src) else 0 dst_base = 1 if self.isSwitch(dst) else 0 if sport is None: sport = len(self.ports[src]) + src_base if dport is None: dport = len(self.ports[dst]) + dst_base self.ports[src][dst] = sport self.ports[dst][src] = dport def nodes(self, sort=True): "Return nodes in graph" if sort: return self.sorted( self.g.nodes() ) else: return self.g.nodes() def isSwitch(self, n): '''Returns true if node is a switch.''' info = self.node_info[n] return info and info.get('isSwitch', False) def switches(self, sort=True): '''Return switches. sort: sort switches alphabetically @return dpids list of dpids ''' return [n for n in self.nodes(sort) if self.isSwitch(n)] def hosts(self, sort=True): '''Return hosts. sort: sort hosts alphabetically @return dpids list of dpids ''' return [n for n in self.nodes(sort) if not self.isSwitch(n)] def links(self, sort=True): '''Return links. sort: sort links alphabetically @return links list of name pairs ''' if not sort: return self.g.edges() else: links = [tuple(self.sorted(e)) for e in self.g.edges()] return sorted( links, key=naturalSeq ) def port(self, src, dst): '''Get port number. @param src source switch name @param dst destination switch name @return tuple (src_port, dst_port): src_port: port on source switch leading to the destination switch dst_port: port on destination switch leading to the source switch ''' if src in self.ports and dst in self.ports[src]: assert dst in self.ports and src in self.ports[dst] return (self.ports[src][dst], self.ports[dst][src]) def linkInfo( self, src, dst ): "Return link metadata" src, dst = self.sorted([src, dst]) return self.link_info[(src, dst)] def setlinkInfo( self, src, dst, info ): "Set link metadata" src, dst = self.sorted([src, dst]) self.link_info[(src, dst)] = info def nodeInfo( self, name ): "Return metadata (dict) for node" info = self.node_info[ name ] return info if info is not None else {} def setNodeInfo( self, name, info ): "Set metadata (dict) for node" self.node_info[ name ] = info @staticmethod def sorted( items ): "Items sorted in natural (i.e. alphabetical) order" return sorted(items, key=natural)
# number_of_fake_nodes = 5 min_value_x = min(x) max_value = max(y) min_value = min(y) count = 1 degreeMap = nx.degree(random_bipartite_graph) sortedval = sorted(degreeMap.items(),key = lambda x : x[1],reverse=True) for val in range(10): if val == 5: for node_value in range(min_value_x+10): node = random_bipartite_graph.nodes()[node_value] if not node_value in corrupted_node: corrupted_node[node_value] = {} corrupted_node[node_value]['old'] = degreeMap[node_value] compare_val = min_value + 0.9*(max_value - min_value) for node_val in range(min_value,int(compare_val)): edgeArr = random_bipartite_graph.edges() if not (node,node_val) in edgeArr: random_bipartite_graph.add_edge(node,node_val) pageRankMap = nx.pagerank(random_bipartite_graph) for i in pageRankMap: if i not in pageRankNodeMap: pageRankNodeMap[i] = []
class Network(HasTraits): """ The implementation of the Connectome Networks """ implements(INetwork) # Network ID, from parsed GraphML the graphid networkid = '' # Network name networkname = Str # network name as seen in the TreeView name = Str # Is it an hierarchical network? hierarchical = CBool(False) # TODO: later, also Hypergraph?! # see: http://www.ploscompbiol.org/article/info%3Adoi%2F10.1371%2Fjournal.pcbi.1000385 hypergraph = CBool(False) # Directionality of the Network, {True: 'directed', False: 'undirected'} directed = CBool(False) # metadata for the network metadata = Dict # NodeKeys from the parsed GraphML # These are Dict of Dict, all having strings nodekeys = {} # Edgekeys, from parsed GraphML edgekeys = {} # A NetworkX AttrGraph containing all the information graph = Any # Surface containers surfaces = List(ISurfaceContainer) # Surface containers loaded surfaces_loaded = List(ISurfaceContainer) # Volume data volumes = List(IVolume) # Track data tracks = List(ITrackfile) # is this network active, and thus a render manager displayed? active = Bool # the render manager of this network rendermanager = Instance(RenderManager) # DatasourceManager Instance of this network datasourcemanager = Instance(DatasourceManager) # private traits ########### # parent cfile this networks belongs to _parentcfile = Any # filezip of cfile _filezip = DelegatesTo('_parentcfile') # edge parameters for visualization _edge_para = Instance(EdgeParameters) # View traits_view = View( Item('networkname', style = 'readonly'), Item('hierarchical', style = 'simple'), Item('hypergraph', style = 'simple'), Item('directed', style = 'simple'), Item('active', style = 'simple'), title = 'A network', ) def __init__(self, name, src = None, directed = '0', pickled_graph = None, \ hierarchical ='0', hypergraph = '0', graph = None): """ Initializes the network and sets the traits. Parameters ---------- name : string the name of the network src : file handle or StringIO object the source text of the network to parse pickled_graph : NetworkX graph reference to a graph object, src should be None directed : bool Is the network directed? hierarchical : bool Is the network hierarchical? (default: '0') Not implemented yet. hypergraph : bool Is the network a hypergraph? (default: '0') Not implemented yet. """ # initialize the traits self.networkname = name self.directed = int(directed) self.hierarchical = int(hierarchical) self.hypergraph = int(hypergraph) if src is None and not pickled_graph is None: self.load_pickled_graphml(pickled_graph) else: if not src is None: # generates NetworkX Graph self.graph = self.parse_network_graphml(src) elif not graph is None: self.graph = graph else: if self.directed: from networkx import DiGraph self.graph = DiGraph() logger.info("Initialize with empty directed Graph") else: from networkx import Graph self.graph = Graph() logger.info("Initialize with empty undirected Graph") # initializes the weight key of the graph # with the first edgekey if len(self.edgekeys) > 0: edgk = self.edgekeys.keys() if not 'weight' in edgk: self.set_weight_key(edgk[0]) else: # try grabbing first edge from the graph if self.graph.number_of_edges() > 0: it = self.graph.edges_iter(data=True) edg = it.next() if len(edg[2]) > 0: # if it has a weigth key, just leave it edgk = edg[2].keys() if not 'weight' in edgk: self.set_weight_key(edgk[0]) else: pass # logger.error('Cannot set weight key for network : ' + self.networkname) def _name_default(self): return self.networkname def _active_default(self): return False def _active_changed(self , value): if value: n = self.name if ' [Active]' not in n: self.name = "%s [Active]" % n # XXX: do refactor with threaded loading of surfaces # and default spring force layout for graph rendering! # see also TraitsUI Demos: Multi thread demo # load the surface containers data # make a deep copy of the already loaded surface containers import copy self.surfaces = copy.deepcopy(self.surfaces_loaded) for surfcont in self.surfaces: surfcont.load_surface_container() if self.rendermanager is None: self._create_datasourcemanager() self._create_renderer() # if there are no surfaces, initialize # network rendering, but only if dn_positions are given if len(self.surfaces) == 0: logger.debug('No surfaces found. Try to render graph view with dn_position information.') self.rendermanager.datasourcemanager._compute_3DLayout(-1, -1) self.rendermanager.visualize_graph() else: logger.debug('SurfaceContainer found. Try to render 3D View using %s.' % self.surfaces[0].name) if len(self.surfaces[0].surfaces) == 0: logger.debug('Rendering not possible because SurfaceContainer contains no surfaces.') else: logger.debug('Using first surface for rendering.') self.surfaces[0].surfaces[0]._layout_3DView() if not self._parentcfile._workbenchwin is None: #from enthought.pyface.timer.api import do_later from enthought.pyface.api import GUI GUI.invoke_later(self._parentcfile._workbenchwin.status_bar_manager.set, message = '') else: self.name = self.name.replace(' [Active]', '') logger.debug('Close RenderManager scenes') self.rendermanager.close_scenes() logger.debug('All scenes closed.') # FIXME: what is happening in the following? # e.g. for instances. e.g. reset traits? # XXX: this is somehow not correct. do i need to use del # or remove/reset traits? self.rendermanager = None self.datasourcemanager = None self.surfaces = [] def _de_activate(self): """ Toggles the internal state of the activation """ if self.active: self.active = False else: self._parentcfile._workbenchwin.status_bar_manager.message = 'Activating network ...' self.active = True def _edge_parameters(self): """ Dialog to change edge attribute and thresholding """ if self._edge_para is None: self._edge_para = EdgeParameters(self, self.rendermanager.attract.point_scalars_name) self._edge_para.configure_traits() def _create_renderer(self): """ Creates the renderer instance if not yet available and opens the scenes in mayavi """ if self.active: if self.rendermanager is None: logger.debug('Create a RenderManager instance') self.rendermanager = RenderManager(network=self) else: logger.debug('RenderManager instance already running. This is an error.') def _create_datasourcemanager(self): """ Creates the datasource manager instance if not yet available """ if self.active: if self.datasourcemanager is None: logger.debug('Create a DatasourceManager instance') self.datasourcemanager = DatasourceManager(network=self) else: logger.debug('DatasourceManager instance already running. This is an error.') def _render_matrix(self): """ Invokes the connectivity matrix viewer """ # assume the network is activated (i.e. data source generated) # we need the edge parameter instance initialized if self._edge_para is None: self._edge_para = EdgeParameters(self, self.rendermanager.attract.point_scalars_name) logger.debug('Invoke Matrix Viewer...') self.rendermanager.invoke_matrix_viewer() def _trackvis_launch(self): """ Generates scene file and launch Trackvis on the selected nodes """ import tempfile logger.debug('Starting TrackVis ...') # extract selected subgraph selectionlist = self.get_selectiongraph_list() if len(selectionlist) == 0: # message from enthought.traits.ui.message import message message(message = 'No nodes selected for ROI creation!', title = 'Infomessage', buttons = [ 'OK' ], parent = None) tmpgraph = self.graph.subgraph(selectionlist) # extract trackfile temporarily if len(self.tracks) == 0: logger.info('No trackfile found to invoke Trackvis.') return else: # load the first trackfile trackfname = self.tracks[0].load_trackfile_to_file() # find the first valid segmentation volume in the self.volumes list for vol in self.volumes: if vol.segmentation: logger.debug('Found a segmentation volume file. Assume labels are corresponding.') volumefname = vol.load_volume_to_file() break # generate the scene file in the temporary folder tmpscenefile=tempfile.mkstemp(prefix='tmp', suffix='.scene') # generate trackfile generate_scene_file(scenefname=tmpscenefile[1], \ trackfname = trackfname, \ volumefname = volumefname, \ selectiongraph = tmpgraph) # execute trackvis in a thread pref = preference_manager.preferences action = ThreadedTrackvis(tvpath = pref.get('cviewer.plugins.ui.trackvispath'), \ fname = tmpscenefile[1], \ trkfname = trackfname,\ volfname = volumefname) action.start() def add_surface_container(self, surfacecontainer): """ Add a surface container to the loaded list Parameters ---------- surfacecontainer : `ISurfaceContainer` instance a surface container object """ surfacecontainer._networkref = self self.surfaces_loaded.append(surfacecontainer) def add_volume(self, volume): """ Adds a volume to the volumes list Parameters ---------- volume : `IVolume` instance a volume object """ self.volumes.append(volume) def add_trackfile(self, trackfile): """ Adds a trackfile to the tracks list Parameters ---------- trackfile : `ITrackfile` instance a trackfile of type ITrackfile """ self.tracks.append(trackfile) def unselect_all(self): """ Unselects every node in the current network """ if self.datasourcemanager is None: raise Exception('No DatasourceManager. You have to first activate the network and render it.') from numpy import array # get all the nodes graphnodes = self.datasourcemanager._srcobj.relabled_graph.nodes() # and unselect all nodes self.rendermanager._select_nodes(selection_node_array = array(graphnodes)) def select_all(self): """ Selects all nodes in the current network """ if self.datasourcemanager is None: raise Exception('No DatasourceManager. You have to first activate the network and render it.') from numpy import array # get all the nodes graphnodes = self.datasourcemanager._srcobj.relabled_graph.nodes() # and select all nodes self.rendermanager._select_nodes(selection_node_array = array(graphnodes), activate = True) def set_selectiongraph(self, sellist, activate = False): """ Sets the selected nodes in the network to active. Parameters ---------- sellist : array_like a list of nodeids conforming to the NetworkX node id activate : boolean set the selectionlist nodes to activated? """ from numpy import array, int16 graphnodes = self.graph.nodes(data=False) if self.rendermanager is None: raise Exception('No RenderManager. You have to first activate the network and render it.') if len(sellist) == 0: self.unselect_all() return from numpy import array, append tmparr = array([]) for node in sellist: # check if it is a valid graph node id if node in graphnodes: # get the node id as integer j = int(node.lstrip('n'))-1 # extend empty array with node id tmparr = append(tmparr, j) self.rendermanager._select_nodes(selection_node_array = array(tmparr, dtype = int16), activate = activate) def get_selectiongraph_list(self): """ Returns a list of the node ids that were selected in the rendered scene. """ if self.datasourcemanager is None: raise Exception('No DatasourceManager. You have to first activate the network and render it.') import numpy as np sel_list = [] if not self.active: return sel_list selnodesarray = self.datasourcemanager._srcobj.selected_nodes # array with indices where the nodes are selected (==1) idx = np.where(selnodesarray == 1)[0] for i in idx: sel_list.append('n' + str(i + 1)) return sel_list def set_weight_key(self, weight_key = None): """ Sets the weight key in the graph representation of the network. Parameters ---------- weight_key : Str Must be a possible existing edge key """ if not weight_key is None: for u,v,d in self.graph.edges(data=True): self.graph[u][v]['weight']=d[weight_key] return True else: return False def get_matrix(self, weight_key = None): """ Returns the connectivity matrix of the network with the nodes ordered according to their id in the GraphML file. Parameters ---------- weight_key : Str Possible key value of the edges Returns ------- matrix : `Numpy.array` instance The connectivity matrix """ nr_nodes = len(self.graph.nodes()) if not weight_key is None: #FIXME: sanity check if weight_key exists # thanks to Aric Hagberg for u,v,d in self.graph.edges(data=True): self.graph[u][v]['weight']=d[weight_key] nodes = [(lambda nmod:'n'+str(nmod))(node) for node in range(1,nr_nodes + 1)] from networkx import to_numpy_matrix return to_numpy_matrix(self.graph, nodelist = nodes) def toggle_surface(self): """ Toggle the surface for the selected network nodes """ if self.rendermanager is None: raise Exception('No RenderManager. You have to first activate the network and render it.') self.rendermanager._toggle_surface() def show_surface(self): """ Shows the surface for the selected network nodes """ if self.rendermanager is None: raise Exception('No RenderManager. You have to first activate the network and render it.') self.rendermanager._show_surface() def load_pickled_graphml(self, graph): """ Loads a pickled GraphML file Parameters ---------- graph : NetworkX Graph instance A graph instance """ # setting the graph self.graph = graph if self.graph.has_node('n0'): if self.graph.node['n0'].has_key('nodekeys'): # extracting the node keys from the first node self.nodekeys = self.graph.node['n0']['nodekeys'] # extracting the edge keys from the first edge (without explanation) if self.graph.node['n0'].has_key('edgekeys'): self.edgekeys = self.graph.node['n0']['edgekeys'] if self.graph.node['n0'].has_key('graphid'): self.networkid = self.graph.node['n0']['graphid'] # remove node self.graph.remove_node('n0') def _return_default_edgevalue(self, edgekeys, key): """ Looks up if there is a default value defined, otherwise return zero """ if edgekeys[key].has_key('default'): return float(edgekeys[key]['default']) else: return 0.0 def parse_network_graphml(self, path): """ Read network in GraphML format from a path. Parameters ---------- path : string path the the GraphML file Returns ------- graph : NetworkX `Graph` """ import networkx as nx from networkx.utils import _get_fh from lxml import etree # Return a file handle for given path. # Path can be a string or a file handle. # Attempt to uncompress/compress files ending in .gz and .bz2. fh=_get_fh(path,mode='r') tree = etree.parse(fh) # get the root node from parsed lxml root = tree.getroot() # Schema Validation # http://codespeak.net/lxml/validation.html#xmlschema # define the namespace prefixes nsprefix = "{%s}" % root.nsmap[None] nsxlink = "{%s}" % root.nsmap['xlink'] nodekeys = {} edgekeys = {} defaultDirected = [True] # Parse the KEYs for child in root.iterchildren(): if child.tag == (nsprefix+'key'): attribs = child.attrib ddkeys = {} for mchildren in child: if mchildren.tag == (nsprefix+'default'): ddkeys['default'] = mchildren.text elif mchildren.tag == (nsprefix+'desc'): ddkeys['desc'] = mchildren.text if child.attrib['for'] == 'node': # Parse all the node keys # Read in the description and the default (if existing) # dict of dicts for nodes: key1: the id; key2: rest: attr.name, attr.type, desc, default nodekeys[attribs['id']] = {'attr.name' : attribs['attr.name'], \ 'attr.type' : attribs['attr.type']} # add default/desc keys if existing nodekeys[attribs['id']] = ddkeys elif child.attrib['for'] == 'edge': # Parse all the edge keys # Read in the description and the default (if existing) # dict of dicts for edges: key1: the id; key2: rest: attr.name, attr.type, desc, default edgekeys[attribs['id']] = {'attr.name' : attribs['attr.name'], \ 'attr.type' : attribs['attr.type']} # add default/desc keys if existing edgekeys[attribs['id']] = ddkeys else: logger.error("The 'for' attribute of key-tag not known, must be either node or edge") elif child.tag == (nsprefix+'graph'): # start parsing the graph into networkx data structure # create graph depending on (either AttrGraph or AttrDiGraph) # directionality: undirected/directed # version of networkx: # contains self-loops # edges have dicts # data per graph/node/edge for attr, value in child.items(): if attr == 'edgedefault' and value == 'undirected': defaultDirected[0] = False elif attr == 'id': graphid = value if defaultDirected[0]: G = nx.DiGraph() else: G = nx.Graph() # add id, nodekeys and edkeys as traits self.networkid = graphid self.nodekeys = nodekeys self.edgekeys = edgekeys # iterate over all nodes and edges for children in child.iterchildren(): if children.tag == (nsprefix+'node'): # parse the node for attr, value in children.items(): if attr == 'id': # add the node with corresponding id G.add_node(value) # keep node id to store attributes nodeid = value elif attr == (nsxlink+'href'): # add xlink to node dictionary G.node[nodeid]['xlink'] = value else: # node attribute not known logger.warning('The following node attribute is not known and thus discarded:'+ attr + ':' + value) # parse node data, add to node dict for data in children.iterchildren(): # read the keylabel, i.e. the data attribute name keylabel = data.attrib['key'] # is the keylabel in the list of allowed keys if nodekeys.has_key(keylabel): if not data.text == '': # add data to the node's dict G.node[nodeid][keylabel] = data.text else: # no data available, check if default value exists if nodekeys[keylabel].has_key('default'): # add default data to the node's dict G.node[nodeid][keylabel] = nodekeys[keylabel]['default'] logger.debug('Added default value '+ keylabel + ':' + nodekeys[keylabel]['default']) else: logger.warning('Nor data nor default value defined for ' + keylabel) # TODO: Work with exceptions! else: logger.warning("Data entry with key " + keylabel + " not defined.") elif children.tag == (nsprefix+'edge'): # parse the edge # parse its attributes for attr, value in children.items(): if attr == 'id': # no usage of edge id # add the edge with corresponding id src = children.attrib['source'] tar = children.attrib['target'] G.add_edge(src, tar) # keep dest and tar id to store attributes srcid = src tarid = tar elif attr == (nsxlink+'href'): # add xlink to edge dictionary G.edge[srcid][tarid]['xlink'] = value # parse data, and add to the edge dict for data in children.iterchildren(): # read the keylabel, i.e. the data attribute name keylabel = data.attrib['key'] # is the keylabel in the list of allowed keys if self.edgekeys.has_key(keylabel): if not data.text == '': # add data to the edge's dict, assume float!! G.edge[srcid][tarid][keylabel] = float(data.text) else: # no data available, check if default value exists G.edge[srcid][tarid][keylabel] = self._return_default_edgevalue(self.edgekeys, keylabel) data_keys = G.edge[srcid][tarid].keys() # check if we missed some edge keys that are available in the header for k, v in self.edgekeys.items(): if not k in data_keys: G.edge[srcid][tarid][k] = self._return_default_edgevalue(self.edgekeys, k) # return the generated network graph return G
from networkx import Graph entries = Graph() #entries.add_node('@davidmartinb') #entries.add_node('@emartinborregon') entries.add_edge('@davidmartinb','@emartinborregon') #entries.add entries2 = entries.copy() #entries.add_node('@davidmartinb') #entries.add_node('@emartinborregon') entries2.add_edge('@davidmartinb','@test') entries.add_edge('@davidmartinb','@emartinborregon') #entries.add print set(entries2.nodes())-set(entries.nodes()) edges1=entries.edges() entries2.remove_edges_from( edges1 ) print entries2.edges()
class HybridNetworkCase(unittest.TestCase): def setUp(self): #super(HybridNetworkCase, self).__init__() self.G = Graph() self.G.add_node(0, coord=(0., 0.)) self.G.add_node(1, coord=(1., 0.)) self.G.add_node(2, coord=(-0.5, np.sqrt(3.)/2.)) self.G.add_node(3, coord=(0.5, np.sqrt(3.)/2.)) self.G.add_node(4, coord=(1.5, np.sqrt(3.)/2.)) self.G.add_node(5, coord=(0., np.sqrt(3.))) self.G.add_node(6, coord=(1., np.sqrt(3.))) self.G.G_nav = Graph() l = np.sqrt(3.) #pouet = [] # Put six points inside the central sector center = np.array([0.5, l/2.]) for i in range(6): angle = float(i)/6.*2.*np.pi point = center + 0.25*np.array([np.cos(angle), np.sin(angle)]) #pouet.append(list(point)) self.G.G_nav.add_node(i, coord=point) # Put two points in the 6 outer sectors for i in range(12): angle = 1./24.*(2.*np.pi) + float(i)/12.*(2.*np.pi) point = center + 1.25*np.array([np.cos(angle), np.sin(angle)]) self.G.G_nav.add_node(6 + i, coord=point) self.G.G_nav.add_node(18, coord=center) self.G.airports = [] self.G.G_nav.airports = [] def get_airports(G): return G.airports self.G.get_airports = types.MethodType(get_airports, self.G) self.G.G_nav.get_airports = types.MethodType(get_airports, self.G.G_nav) self.G.G_nav.navpoints_borders = [] def give_nodes_to_secs(self): self.G.node[3]['navs'] = list(range(6)) + [18] self.G.node[0]['navs'] = [13, 14] self.G.node[1]['navs'] = [15, 16] self.G.node[2]['navs'] = [11, 12] self.G.node[4]['navs'] = [6, 17] self.G.node[5]['navs'] = [9, 10] self.G.node[6]['navs'] = [7, 8] for i in range(6): self.G.G_nav.node[i]['sec'] = 3 self.G.G_nav.node[18]['sec'] = 3 self.G.G_nav.node[6]['sec'] = self.G.G_nav.node[17]['sec'] = 4 self.G.G_nav.node[7]['sec'] = self.G.G_nav.node[8]['sec'] = 6 self.G.G_nav.node[9]['sec'] = self.G.G_nav.node[10]['sec'] = 5 self.G.G_nav.node[11]['sec'] = self.G.G_nav.node[12]['sec'] = 2 self.G.G_nav.node[13]['sec'] = self.G.G_nav.node[14]['sec'] = 0 self.G.G_nav.node[15]['sec'] = self.G.G_nav.node[16]['sec'] = 1 def give_full_connections(self): for i in range(7): if i!=3: self.G.add_edge(3, i) periph_secs = [0, 1, 4, 6, 5, 2] for idx, n in enumerate(periph_secs): self.G.add_edge(n, periph_secs[(idx+1)%len(periph_secs)]) for i in range(6): self.G.G_nav.add_edge(18, i) self.G.G_nav.add_edge(i, (i+1)%6) self.G.G_nav.add_edge(i, 2*i+6) coin = (2*i+5) if (2*i+5)!=5 else 17 self.G.G_nav.add_edge(i, coin) for i in range(6, 18): coin = i+1 if i+1 != 18 else 6 self.G.G_nav.add_edge(i, coin) # print "TEST: Creating the following edges:" # print self.G.G_nav.edges() def do_voronoi(self): self.G, vor = compute_voronoi(self.G, xlims=(-1., 2.), ylims=(-0.5, 2.5)) self.G.polygons = {i:pol for i, pol in self.G.polygons.items() if type(pol)==type(Polygon())} self.G.global_shape = cascaded_union(self.G.polygons.values()) def show_network(self, secs=True, navs=True, show=True): if secs: plt.scatter(*zip(*[self.G.node[n]['coord'] for n in self.G.nodes()]), marker='s', color='r', s=50) if navs: plt.scatter(*zip(*[self.G.G_nav.node[n]['coord'] for n in self.G.G_nav.nodes()]), marker='o') if show: plt.show() def show_polygons(self, show=True): for pol in self.G.polygons.values(): plt.fill(*zip(*list(pol.exterior.coords)), alpha=0.4) if show: plt.show()
class WishPool: def __init__( self, wishes, min_edge_score = MIN_EDGE_SCORE, # min_number_of_edges = MIN_NUMBER_OF_EDGES, connector = default_connector ): """ A filterable pool of wishes represented as nodes. Is used to find relations between wishes. @param connector: default connector is jaccard @return: """ self.graph = Graph() self.min_edge_weight = min_edge_score # self.min_number_of_edges = min_number_of_edges for wish in wishes: self.graph.add_node( wish ) # loops through the existing nodes in the graph for other in self.graph.nodes_iter(): # compares candidate to all existing nodes except itself if other != wish and other.person != wish.person: score = connector( wish, other ) if score > self.min_edge_weight: self.graph.add_edge( wish, other, weight=score ) ## processes the graph, excludes lonely nodes self.connected_nodes = self.update_connected_nodes() debug_graph(self.graph, message="Connected nodes are set") self.lonely_nodes = self.update_lonely_nodes() self.update_cliques() ## evaluates alternatives, gathers suggestions for each wish # this implies that some cliques occur twice self.suggestions = self.update_suggestions() def update_connected_nodes( self ): connected = set() for n in self.graph.edges(): connected.add( n[0] ) return connected def update_lonely_nodes( self ): whole_graph = set( self.graph.nodes() ) return whole_graph.difference( self.connected_nodes ) def remove_lonely_nodes( self ): raise NotImplementedError def update_cliques( self ): result = set() for c in find_cliques( self.graph ): if len(c) > 1: result.add( Clique(c) ) self.cliques = result return result def get_distributed_cliques( self ): self.cliques_for_wish = {} for n in self.graph.nodes(): clique_buffer = [] for c in self.cliques: if n in c.nodes: clique_buffer.append( c ) if len(clique_buffer): self.cliques_for_wish[n.pk] = [ c for c in clique_buffer if len(c.nodes) > 1 ] return self.cliques_for_wish def get_conflicting_cliques( self ): result = {} for w,c in self.get_distributed_cliques(): if len(c) > 1: result[w] = c return result def update_suggestions( self ): suggestions = [] for wish_pk, cliques in self.get_distributed_cliques().items(): suggestion = Suggestion( Wish.objects.get(pk=wish_pk), cliques ) suggestions.append( suggestion ) self.suggestions = suggestions return suggestions def create_groups( self ): distinct_cliques = set() for s in self.suggestions: distinct_cliques.add( s.get_best_clique() ) for c in distinct_cliques: c.create_group() def get_suggestion_pool( self ): return SuggestionPool( self.suggestions )
class LangGraph(object): """ A graph of all the relationships in a document and/or sentence """ def __init__(self, directed=False): """ Builds a graph out of the given document """ self.isDirected = directed #a graph that is meant to be full of class Instance if self.isDirected: self.graph = DiGraph() else: self.graph = Graph() self.start = None #an Instance #keep the graph also according to temporal, redundant probably needs #refactoring self.temporal = None self.temporalMap = None def setStart(self, start): """ Sets the starting instance, also builds the temporal ordering of the graph """ self.start = start self.temporal = self.narrativeOrder() self.temporalMap = self.narrativeMapping() def indexToInst(self, index): """ Returns the instance corresponding to the given index """ result = index #if the index is an int, lookup the instance associated with it if type(index) == int: result = self.temporal[index] return result def instToIndex(self, instance): """ Return the index associated with the instance """ return self.temporalMap[instance] def narrativeOrder(self): """ Returns the instances in narrative order """ results = [] node = self.start prev = None #while there are more nodes, keep adding them while node is not None: #record the current node results.append(node) #get the connected nodes fringe = [n for n in self.adj(node, WORD_EDGE) if n != prev] nextNode = fringe[0] if fringe else None #advance to the next node prev = node node = nextNode return results def narrativeMapping(self): """ Makes the mapping from instances to their narrative index """ return {inst:i for i,inst in enumerate(self.temporal)} def addNode(self, node): """ Adds a node to the graph """ self.graph.add_node(node) def addEdge(self, start, end, type): """ Adds an edge between the two instances """ #if the edge exists, just add the type if self.graph.has_edge(start, end): self.addType(start, end, type) else: self.graph.add_edge(start, end, TYPES=set([type])) def removeEdge(self, start, end, edgeType): """ Removes an edge with a given type from the edge type """ #remove the type self.removeType(start, end, edgeType) #if there are no types, remove the edge itself types = self.edgeTypes(start, end) #remove the edge if not len(types) and self.graph.has_edge(start, end): self.graph.remove_edge(start, end) def addType(self, start, end, type): """ Adds a type between the edges """ #look for existing types types = self.graph[start][end].get(TYPES, set()) #add the new type types.add(type) self.graph[start][end][TYPES] = types def removeType(self, start, end, edgeType): """ Removes the type on the edge """ for prefix in [PARENT, CHILD]: edgeType = removePrefix(prefix, edgeType) types = self.graph[start][end][TYPES] #if the types contains the edge, remove if edgeType in types: types.remove(edgeType) def hasType(self, start, end, type): """ Returns true if the edge between the two nodes has the given type """ return type in self.edgeTypes(start, end) def singleEdgeTypes(self, start, end): """ Returns the types on the edge if any, or an empty set is returned """ #make sure we are using instances rather than indexes start = self.indexToInst(start) end = self.indexToInst(end) data = self.graph.get_edge_data(start,end) result = set() #if there is data, get the types if data is not None: result = data.get(TYPES, set()) return result def edgeTypes(self, start, end): """ Returns the types on the edge if any, or an empty set is returned """ if self.isDirected: parent = addPrefixes(PARENT, self.singleEdgeTypes(end, start)) child = addPrefixes(CHILD, self.singleEdgeTypes(start, end)) types = parent.union(child) else: types = self.singleEdgeTypes(start, end) return types def allEdgeTypes(self): """ Returns all the edge types """ results = set() #collect all the edges with all the types for s,e,types in self.allEdges(): #look up the edge types to make sure everything is covered for edgeType in types: results.add(edgeType) #add in the reverse types for edgeType in self.edgeTypes(e,s): results.add(edgeType) return results def allEdges(self): """ Yield all the edges in the graph """ for start, end in self.graph.edges(): yield start, end, self.edgeTypes(start, end) def contains(self, instance): """ Returns true if the graph contains the instance """ return self.graph.has_node(instance) def instances(self): """ Return all the instances in the graph """ return self.graph.nodes() def edges(self, instance): """ Returns all the edges connected to this instance """ inst = self.indexToInst(instance) #make get the directed edges if self.isDirected: results = [t for _, t in self.graph.out_edges(inst)] + [t for t, _ in self.graph.in_edges(inst)] else: results = self.graph.adj[inst] return results def docType(self): """ Returns the document type (String) """ return self.temporal[0].event.docType def adj(self, instance, type=None): """ Returns the adjancent node with a given type """ return [other for other in self.edges(instance) if self.hasType(instance, other, type) or type is None] def nonNarrativeAdj(self, instance, returnIndex=False): """ Returns the nodes that are not adjancent to the given instance """ results = [] #add each node if it has a non-narrative (temporal) connection for node in self.edges(instance): #get the non narrative types edgeTypes = nonNarrativeTypes(self.edgeTypes(instance, node)) #if there is a non-narrative edge, add it if edgeTypes: #lookup the index of the node nodeMarker = self.instToIndex(node) if returnIndex else node results.append((nodeMarker, edgeTypes)) return results def words(self): """ Returns the words in narrative order """ return [t.word for t in self.tokens()] def tokens(self): """ Returns the tokens in narrative order """ return [i.token for i in self.temporal] def labels(self): """ Returns the sequence of labels for the instances """ return [i.event.type for i in self.temporal] def removeAny(self, blackList): """ Removes any nodes/tokens/instances that match the words in the blacklist """ #if a token or its lemma match any of the words in the blacklist #mark it for removal toRemove = {inst.token for inst in self.temporal if inst.token.word.lower() in blackList or inst.token.lemma.lower() in blackList} self.removeNodes(toRemove) def removeNodes(self, tokens): """ Removes the token from the graph """ startLen = len(self) #mark all the instances/indexes to remove instances = {inst:i for inst,i in self.temporalMap.items() if inst.token in tokens} #determine the remaining nodes remaining = sorted(list(set(range(startLen)) - {i for i in instances.values()})) #add in all the bypasses for startIndex, endIndex in iterPairs(remaining): start = self.temporal[startIndex] end = self.temporal[endIndex] self.addEdge(start, end, WORD_EDGE) #remove the edges for inst in instances: self.graph.remove_node(inst) #if there are remaining nodes then reset the temporal mapping if remaining: startIndex = min(remaining) self.start = self.temporal[startIndex] #redo narrative order self.temporal = self.narrativeOrder() self.temporalMap = self.narrativeMapping() else: self.start = None self.temporal = [] self.temporalMap = {} def copy(self): """ Performs a shallow copy of the graph """ newGraph = LangGraph(self.isDirected, self.entEdges) #create new instances newInst = {i:me.Instance(copy(i.token), i.event) for i in self.temporal} #add in all the edges for start, end in self.graph.edges(): for eType in self.edgeTypes(start, end): newGraph.addEdge(newInst[start], newInst[end], eType) newGraph.setStart(newInst[self.start]) return newGraph def graphString(self): """ Returns the graph as a string """ return " ".join([t.word for t in self.tokens()]) def __len__(self): """ Returns the number of nodes (tokens) in the graph """ return len(self.graph) def __repr__(self): """ Returns a summary string of the graph """ return "LangGraph {} nodes, {} edges".format(len(self.graph.nodes()), len(self.graph.edges()))
def make_steiner_tree(G, voi, generator=None): mst = Graph() for v in voi: if not v in G: raise ValueError, "make_steiner_tree(): Some vertice not in original graph" if len(voi) == 0: return mst if len(voi) == 1: mst.add_node(voi[0]) return mst # Initially, use (a version of) Kruskal's algorithm to extract a minimal spanning tree # from a weighted graph. This algorithm differs in that only a subset of vertices are # going to be present in the final subgraph (which is not truely a MST - must use Prim's # algorithm later. # extract all shortest paths among the voi heapq = [] paths = {} # load all the paths bwteen the Steiner vertices. Store them in a heap queue # and reconstruct the MST of the complete graph using Kruskal's algorithm for i in range(len(voi) - 1): v1 = voi[i] for v2 in voi[i+1:]: result = bidirectional_dijkstra(G, v1, v2) if result == False: raise RuntimeError, "The two vertices given (%s, %s) don't exist on the same connected graph" % (v1, v2) #print "The two vertices given (%s, %s) don't exist on the same connected graph" % (v1, v2) distance, vertList = result keys = [v1, v2] keys.sort() key = "%s:%s" % tuple(keys) paths[key] = (vertList) heappush(heapq, (distance, v1, v2)) # construct the minimum spanning tree of the complete graph while heapq: w, v1, v2 = heappop(heapq) # if no path exists yet between v1 and v2, add this one if v1 not in mst or v2 not in mst or not has_path(mst, v1, v2): mst.add_edge(v1, v2,weight=w) # check if the graph is tree and correct sTree = set(mst.nodes()) sSteiner = set(voi) if sTree ^ sSteiner: raise RuntimeError, 'Failed to construct MST spanning tree' # reconstruct subgraph of origGraph using the paths if generator is None: subgraph = Graph() else: subgraph = generator() for edge in mst.edges_iter(data=True): keys = [edge[0],edge[1]] keys.sort() key = "%s:%s" % tuple(keys) vList = paths[key] for i in range(len(vList) - 1): v1 = vList[i] v2 = vList[i+1] w = G[v1][v2] subgraph.add_edge(v1, v2, w) # get rid of possible loops - result will be a true MST subgraph = make_prim_mst(subgraph, generator) # remove intermediate nodes in paths that are not in list of voi return _trimTree(subgraph, voi)
class SocialNetwork(object): """Object oriented interface for conducting social network analysis.""" valid_indexes = [] for index_name in conf.INDEXES.keys(): valid_indexes.append(index_name) cache = None def __init__(self): logging.info("libSNA object created.") self.graph = Graph() self.measures = {} self.nodesmeasures = {} self.edgesmeasures = {} for index in self.valid_indexes: self.measures[index] = None def getNodes(self): nodes = self.graph.nodes() nodes.sort() return nodes def getEdges(self): edges = self.graph.edges() return edges def loadGraph(self, nodes, edges): logging.info("Loading network from input variables") for node in nodes: self.graph.add_node(node) for edge in edges: self.graph.add_edge(edge[0], edge[1]) self.graph.name = "Social Network" logging.info("Finished loading network.") def runMeasure(self, measure_name, backend): if measure_name in self.valid_indexes: eval('self.calculate_' + measure_name.replace(' ', '_') + '(backend)') else: logging.error("Unable to calculate the measure (%s)"%(measure_name)) def returnResults(self, measure_name, value = 'value'): if measure_name in self.valid_indexes: if value == 'value': return self.measures[measure_name] elif value == 'nodes': return self.nodesmeasures[measure_name] elif value == 'edges': return self.edgesmeasures[measure_name] else: return None def displayResults(self, measure_name, value = 'value'): if measure_name in self.valid_indexes: if value == 'value': logging.info((conf.INDEX_TYPES[measure_name] + '.') % self.measures[measure_name]) elif value == 'nodes': logging.info(str(self.nodesmeasures[measure_name] or '<null>')) elif value == 'edges': logging.info(str(self.edgesmeasures[measure_name] or '<null>')) else: logging.error("Unable to calculate the measure (%s)"%(measure_name)) def calculateMeasures(self, backend=False): for measure_name in self.valid_indexes: self.runMeasure(measure_name, backend=False) def calculate_density(self, backend=False): logging.info("Calculating density.") nodes = self.graph.nodes() edges = self.graph.edges() tot_edges = float(len(nodes) * (len(nodes)-1)) tot_edges = tot_edges / 2 num_edges = float(len(edges)) w = {} for n1 in nodes: for n2 in nodes: w[n1,n2] = 0.0 for n1,n2 in edges: w[n1,n2] = 1.0 self.measures['density'] = num_edges / tot_edges * 100 self.nodesmeasures['density'] = None self.edgesmeasures['density'] = w def calculate_geodesic(self, backend=False): logging.info("Calculating geodesic.") path = self.floyd_warshall(backend) nodes = self.graph.nodes() dividend = 0 geodesic = float(0) geodesic_edges = {} for i in nodes: for j in nodes: try: geodesic_edges[i,j] = path[i,j] geodesic += path[i,j] dividend += 1 except KeyError: pass geodesic /= dividend self.measures['geodesic'] = geodesic self.nodesmeasures['geodesic'] = None self.edgesmeasures['geodesic'] = geodesic_edges def calculate_fragmentation(self, backend=False): logging.info("Calculating fragmentation.") nodes = self.graph.nodes() w = self.floyd_warshall(backend) fragmentation = float(0) for i in nodes: for j in nodes: try: w[i,j] except KeyError: fragmentation += 1 pass fragmentation /= len(nodes)*(len(nodes)-1) self.measures['fragmentation'] = fragmentation * 100 self.nodesmeasures['fragmentation'] = None self.edgesmeasures['fragmentation'] = w def calculate_diameter(self, backend=False): logging.info("Calculating diameter.") path = self.floyd_warshall(backend) nodes = self.graph.nodes() diameter = float(0) for i in nodes: for j in nodes: try: diameter = max(diameter, path[i,j]) except KeyError: pass self.measures['diameter'] = diameter self.nodesmeasures['diameter'] = None self.edgesmeasures['diameter'] = path def calculate_degree(self, backend=False): logging.info("Calculating degree.") degrees = degree_centrality(self.graph) degree = float(sum(degrees.values())/len(degrees.values())) self.measures['degree'] = degree * 100 self.nodesmeasures['degree'] = degrees self.edgesmeasures['degree'] = None def calculate_centralization(self, backend=False): logging.info("Calculating centralization.") degrees = degree_centrality(self.graph) centralization = float(0) maxdegree = max(degrees.values()) for degree in degrees.values(): centralization += maxdegree-degree centralization /= len(degrees.values())-1 self.measures['centralization'] = centralization * 100 self.nodesmeasures['centralization'] = degrees self.edgesmeasures['centralization'] = None def calculate_closeness(self, backend=False): logging.info("Calculating closeness.") closenesses = closeness_centrality(self.graph) closeness = float(sum(closenesses.values())/len(closenesses.values())) self.measures['closeness'] = closeness * 100 self.nodesmeasures['closeness'] = closenesses self.edgesmeasures['closeness'] = None def calculate_eigenvector(self, backend=False): logging.info("Calculating eigenvector.") eigenvectors = eigenvector_centrality(self.graph) eigenvector = float(sum(eigenvectors.values())/len(eigenvectors.values())) self.measures['eigenvector'] = eigenvector * 100 self.nodesmeasures['eigenvector'] = eigenvectors self.edgesmeasures['eigenvector'] = None def calculate_betweenness(self, backend=False): logging.info("Calculating betweenness.") betweennesses = betweenness_centrality(self.graph) betweenness = float(sum(betweennesses.values())/len(betweennesses.values())) self.measures['betweenness'] = betweenness * 100 self.nodesmeasures['betweenness'] = betweennesses self.edgesmeasures['betweenness'] = None def calculate_cliques(self, backend=False): logging.info("Calculating cliques.") cliques = list(find_cliques(self.graph)) w = {} nodes = self.graph.nodes() for node in nodes: w[node] = 0.0 for clique in cliques: if node in clique: w[node] += 1 self.measures['cliques'] = len(cliques) self.nodesmeasures['cliques'] = w self.edgesmeasures['cliques'] = None def calculate_comembership(self, backend=False): logging.info("Calculating comembership.") nodes = self.graph.nodes() n = len(nodes) if not backend and n > 500: raise network_big.NetworkTooBigException(n) cliques = list(find_cliques(self.graph)) w = {} for clique in cliques: for node1 in clique: for node2 in clique: try: w[node1,node2] += 1 except KeyError: w[node1,node2] = 1 nodes = w.keys() comembership = float(0) for node1, node2 in nodes: if node1 != node2: comembership += w[node1,node2] num_nodes = len(self.graph.nodes()) comembership /= num_nodes*(num_nodes-1) self.measures['comembership'] = comembership self.nodesmeasures['comembership'] = None self.edgesmeasures['comembership'] = w def calculate_components(self, backend=False): logging.info("Calculating components.") components = nx.connected_component_subgraphs(self.graph) w = {} nodes = self.graph.nodes() for node in nodes: w[node] = 0.0 for component in components: if len(component) > 1: for node in component: w[node] += 1 self.measures['components'] = len(components) self.nodesmeasures['components'] = w self.edgesmeasures['components'] = None def floyd_warshall(self, backend): nodes = self.graph.nodes() if not backend and len(nodes) > 400: raise network_big.NetworkTooBigException(len(nodes)) logging.info("Computing Floyd-Warshall.") infvalue = 127 #sys.maxint F = nx.floyd_warshall_numpy(self.graph, dtype=np.int8, infvalue=infvalue) w = {} for i in range(0, len(nodes)): for j in range(0, len(nodes)): if not F[i,j] == infvalue: w[nodes[i],nodes[j]] = F[i,j] return w
class Topo(object): '''Data center network representation for structured multi-trees.''' def __init__(self): '''Create Topo object. ''' self.g = Graph() self.node_info = {} # dpids hash to Node objects self.edge_info = {} # (src_dpid, dst_dpid) tuples hash to Edge objects self.ports = {} # ports[src][dst] is port on src that connects to dst self.id_gen = NodeID # class used to generate dpid def add_node(self, dpid, node): '''Add Node to graph. @param dpid dpid @param node Node object ''' self.g.add_node(dpid) self.node_info[dpid] = node def add_edge(self, src, dst, edge = None): '''Add edge (Node, Node) to graph. @param src src dpid @param dst dst dpid @param edge Edge object ''' src, dst = tuple(sorted([src, dst])) self.g.add_edge(src, dst) if not edge: edge = Edge() self.edge_info[(src, dst)] = edge self.add_port(src, dst) def add_port(self, src, dst): '''Generate port mapping for new edge. @param src source switch DPID @param dst destination switch DPID ''' src_base = SWITCH_PORT_BASE if self.is_switch(src) else 0 dst_base = SWITCH_PORT_BASE if self.is_switch(dst) else 0 if src not in self.ports: self.ports[src] = {} if dst not in self.ports[src]: # num outlinks self.ports[src][dst] = len(self.ports[src]) + src_base if dst not in self.ports: self.ports[dst] = {} if src not in self.ports[dst]: # num outlinks self.ports[dst][src] = len(self.ports[dst]) + dst_base def node_enabled(self, dpid): '''Is node connected, admin on, powered on, and fault-free? @param dpid dpid @return bool node is enabled ''' ni = self.node_info[dpid] return ni.connected and ni.admin_on and ni.power_on and not ni.fault def nodes_enabled(self, dpids, enabled = True): '''Return subset of enabled nodes @param dpids list of dpids @param enabled only return enabled nodes? @return dpids filtered list of dpids ''' if enabled: return [n for n in dpids if self.node_enabled(n)] else: return dpids def nodes(self, enabled = True): '''Return graph nodes. @param enabled only return enabled nodes? @return dpids list of dpids ''' return self.nodes_enabled(self.g.nodes(), enabled) def nodes_str(self, dpids): '''Return string of custom-encoded nodes. @param dpids list of dpids @return str string ''' return [str(self.id_gen(dpid = dpid)) for dpid in dpids] def is_switch(self, n): '''Returns true if node is a switch.''' return self.node_info[n].is_switch def switches(self, enabled = True): '''Return switches. @param enabled only return enabled nodes? @return dpids list of dpids ''' nodes = [n for n in self.g.nodes() if self.is_switch(n)] return self.nodes_enabled(nodes, enabled) def hosts(self, enabled = True): '''Return hosts. @param enabled only return enabled nodes? @return dpids list of dpids ''' def is_host(n): '''Returns true if node is a host.''' return not self.node_info[n].is_switch nodes = [n for n in self.g.nodes() if is_host(n)] return self.nodes_enabled(nodes, enabled) def edge_enabled(self, edge): '''Is edge admin on, powered on, and fault-free? @param edge (src, dst) dpid tuple @return bool edge is enabled ''' src, dst = edge src, dst = tuple(sorted([src, dst])) ei = self.edge_info[tuple(sorted([src, dst]))] return ei.admin_on and ei.power_on and not ei.fault def edges_enabled(self, edges, enabled = True): '''Return subset of enabled edges @param edges list of edges @param enabled only return enabled edges? @return edges filtered list of edges ''' if enabled: return [e for e in edges if self.edge_enabled(e)] else: return edges def edges(self, enabled = True): '''Return edges. @param enabled only return enabled edges? @return edges list of dpid pairs ''' return self.edges_enabled(self.g.edges(), enabled) def edges_str(self, dpid_pairs): '''Return string of custom-encoded node pairs. @param dpid_pairs list of dpid pairs (src, dst) @return str string ''' edges = [] for pair in dpid_pairs: src, dst = pair src = str(self.id_gen(dpid = src)) dst = str(self.id_gen(dpid = dst)) edges.append((src, dst)) return edges def port(self, src, dst): '''Get port number. @param src source switch DPID @param dst destination switch DPID @return tuple (src_port, dst_port): src_port: port on source switch leading to the destination switch dst_port: port on destination switch leading to the source switch ''' if src in self.ports and dst in self.ports[src]: assert dst in self.ports and src in self.ports[dst] return (self.ports[src][dst], self.ports[dst][src]) def enable_edges(self): '''Enable all edges in the network graph. Set admin on, power on, and fault off. ''' for e in self.g.edges(): src, dst = e ei = self.edge_info[tuple(sorted([src, dst]))] ei.admin_on = True ei.power_on = True ei.fault = False def enable_nodes(self): '''Enable all nodes in the network graph. Set connected on, admin on, power on, and fault off. ''' for node in self.g.nodes(): ni = self.node_info[node] ni.connected = True ni.admin_on = True ni.power_on = True ni.fault = False def enable_all(self): '''Enable all nodes and edges in the network graph.''' self.enable_nodes() self.enable_edges() def name(self, dpid): '''Get string name of node ID. @param dpid DPID of host or switch @return name_str string name with no dashes ''' return self.id_gen(dpid = dpid).name_str() def ip(self, dpid): '''Get IP dotted-decimal string of node ID. @param dpid DPID of host or switch @return ip_str ''' return self.id_gen(dpid = dpid).ip_str()
def multigraph_to_graph(g: MultiGraph) -> Graph: gx = Graph() gt = Graph(g) gx.add_nodes_from(gt.nodes()) gx.add_edges_from(gt.edges()) return gx
def run(self, manager): manager.logger.info("=" * 80) manager.logger.info("Assembling with Connected Components Assembly strategy") bg = manager.data["gos-asm"]["bg"] log_bg_stats(bg=bg, logger=manager.logger) target_multicolor = manager.data["gos-asm"]["target_multicolor"] assembly_cnt = 0 ap_header_printed = False kbreaks = [] for cc_cnt, cc in enumerate(bg.connected_components_subgraphs(copy=False)): possible_assemblies_graph = Graph() for vertex in (v for v in cc.nodes() if v.is_regular_vertex): if suitable_for_assembly_fragment_ends_vertex(graph=bg, reg_vertex=vertex, target_multicolor=target_multicolor): possible_assemblies_graph.add_node(vertex) if len(list(possible_assemblies_graph.nodes())) > 1000: continue for v1, v2 in itertools.combinations(list(possible_assemblies_graph.nodes()), 2): if assembly_is_allowed(graph=bg, vertex1=v1, vertex2=v2, target_multicolor=target_multicolor, data=manager.data): possible_assemblies_graph.add_edge(v1, v2) reg_vertices_for_assembly = set() for pag_cc in nx.connected_component_subgraphs(possible_assemblies_graph, copy=False): if len(list(pag_cc.nodes())) != 2: continue reg_vertices_for_assembly.add(tuple(pag_cc.nodes())) for vertex_pair in reg_vertices_for_assembly: v1, v2 = vertex_pair if v1.block_name == v2.block_name: continue for color in target_multicolor.colors: iedge1 = get_irregular_edge_by_vertex_color(graph=bg, vertex=v1, color=color) iedge2 = get_irregular_edge_by_vertex_color(graph=bg, vertex=v2, color=color) s_edge = bg.get_condensed_edge(vertex1=v1, vertex2=v2) if bg.has_edge(vertex1=v1, vertex2=v2) else None r1_name, r1_dir = get_repeat_info(iedge1) r2_name, r2_dir = get_repeat_info(iedge2) r1_entry = get_repeat_entry(repeat_name=r1_name, repeat_direction=r1_dir) r2_entry = get_repeat_entry(repeat_name=r2_name, repeat_direction=r2_dir) repeat_info = { "repeat_name_1": r1_name, "repeat_name_2": r2_name, "repeat_dir_1": r1_dir, "repeat_dir_2": r2_dir } try: repeat_guidance = get_repeat_guidance(genome=color, repeat1_entry=r1_entry, repeat2_entry=r2_entry, data=manager.data) except nx.networkx.exception.NetworkXNoPath: raise Exception("Pair of edges must suitable for assembly with repeats guidance") repeat_info["repeat_guidance"] = repeat_guidance evolutionary_scenarios = {} full_ie1_multicolor = get_full_irregular_multicolor(vertex=v1, data=manager.data, graph=bg) full_ie2_multicolor = get_full_irregular_multicolor(vertex=v2, data=manager.data, graph=bg) sedge_multicolor = s_edge.multicolor if s_edge is not None else Multicolor() for e_scenario_name, e_scenario in non_conflicting_evolutionary_scenarios: evolutionary_scenarios[e_scenario_name] = get_assembly_score(full_ie1_multicolor=full_ie1_multicolor, full_ie2_multicolor=full_ie2_multicolor, sedge_multicolor=sedge_multicolor, target_multicolor=target_multicolor, evolutionary_scenario=e_scenario, data=manager.data) api = AssemblyPointInfo(support_edge=s_edge, iedge1=iedge1, iedge2=iedge2, evolutionary_scenarios=evolutionary_scenarios, allowed=True, repeat_info=repeat_info, target_multicolor=target_multicolor, target_color=Multicolor(color)) ap = AssemblyPoint(vertex1=v1, vertex2=v2, additional_information=api) ap.cc_id = cc_cnt if not ap_header_printed: ap_header_printed = True manager.logger.debug("-"*32 + "-"*len(AssemblyPoint.logger_file_header_string())) manager.logger.debug(" "*32 + AssemblyPoint.logger_file_header_string()) manager.logger.debug("-"*32 + "-"*len(AssemblyPoint.logger_file_header_string())) manager.logger.debug("Identified an assembly point :: {ap}".format(ap=ap.as_logger_entry())) manager.data["gos-asm"]["assembly_points"].append(ap) k_break = create_k_break_from_assembly_point(assembly_point=ap) kbreaks.append(k_break) manager.logger.debug("-"*32 + "-"*len(AssemblyPoint.logger_file_header_string())) for k_break in kbreaks: bg.apply_kbreak(kbreak=k_break, merge=False) assembly_cnt += 1 manager.logger.info("Identified and performed {gluing_cnt} assemblies with Connected Components Assembly strategy" "".format(gluing_cnt=assembly_cnt)) log_bg_stats(bg=bg, logger=manager.logger)
elif isinstance(item, Node): pos = utm.from_latlon(item.lat, item.lon, force_zone_number=utm_zone_number) if not utm_zone_number: utm_zone_number = pos[2] graph.add_node(item.id, lat=item.lat, lon=item.lon, pos=pos[:2]) #nodes += 1 items += 1 print('{0} items processed'.format(items), end='\r') print('{0} items processed'.format(items)) if shape_file: n = graph.number_of_nodes() i = 0 print('Apply shapefile') for node in graph.nodes(): p = Point(graph.node[node]['lon'], graph.node[node]['lat']) if not shape_file.contains(p): graph.remove_node(node) i += 1 print('{0}/{1} nodes processed'.format(i, n), end='\r') print('{0}/{1} nodes processed'.format(i, n)) print('Search for orphaned nodes') orphaned = set() n = graph.number_of_nodes() i = 0 for node in graph.nodes_iter(): if graph.degree(node) == 0: orphaned.add(node) i += 1