def get_component_mask(G, test_split=0.0): assert 0 <= test_split <= 1 g = dgl.to_networkx(G).to_undirected() num_nodes = len(g.nodes()) train_mask = np.zeros(num_nodes) train_comp = set() test_mask = None for comp in nx.connected_components(g): if len(comp) > len(train_comp): train_comp = comp for i in train_comp: train_mask[i] = 1 assert sum(train_mask) == len(train_comp) val_mask = 1 - train_mask if test_split: val_idx = np.where(val_mask == 1)[0] test_idx = np.random.choice(val_idx, int(test_split * num_nodes)) test_mask = val_mask[test_idx] val_mask -= test_mask return train_mask, val_mask, test_mask
def _visualize(self, subgraph, nlabel_mapping=None, title=""): num_classes = int(torch.max(self.g.ndata['label']).item()) + 1 nx_g = dgl.to_networkx(subgraph, node_attrs=['label', ExplainerTags.ORIGINAL_ID]) mapping = {i: nx_g.nodes[i][ExplainerTags.ORIGINAL_ID].item() for i in nx_g.nodes.keys()} node_labels = [nx_g.nodes[i]['label'].item() for i in nx_g.nodes.keys()] cmap = plt.get_cmap('cool', num_classes) cmap.set_under('gray') node_kwargs = {'node_size': 400, 'cmap': cmap, 'node_color': node_labels, 'vmin': 0, 'vmax': num_classes-1} label_kwargs = {'labels': mapping, 'font_size': 10} pos = nx.spring_layout(nx_g) ax = plt.gca() for source, target, data in nx_g.edges(data=True): ax.annotate( '', xy=pos[target], xycoords='data', xytext=pos[source], textcoords='data', arrowprops=dict( arrowstyle="->", alpha=1.0, # max(data['att'], 0.1), # TODO - change for transparent visualization mode shrinkA=sqrt(node_kwargs['node_size']) / 2.0, shrinkB=sqrt(node_kwargs['node_size']) / 2.0, connectionstyle="arc3,rad=0.1", )) nx.draw_networkx_labels(nx_g, pos, **label_kwargs) nx.draw_networkx_nodes(nx_g, pos, **node_kwargs) if nlabel_mapping is None: nlabel_mapping = {i: i for i in range(num_classes)} patch_list = [mpatches.Patch(color=cmap(i), label=nlabel_mapping[i]) for i in range(num_classes)] ax.legend(handles=patch_list, title="Label", loc=1) if title is not None: plt.title(title) plt.show()
def dgl_to_nx(graph, edge_map): g = dgl.to_networkx(graph, edge_attrs=['one_hot']) edge_map_r = {v: k for k, v in edge_map.items()} nx.set_edge_attributes( g, {(n1, n2): edge_map_r[d['one_hot'].item()] for n1, n2, d in g.edges(data=True)}, 'label') return g
def add_clustering_coefficients_feature(dataset): for g, _ in dataset: nx_g = dgl.to_networkx(dgl.to_homogeneous(g)) # MultiDiGraph -> Graph nx_g = nx.Graph(nx_g) cc = torch.tensor(list(nx.clustering(nx_g).values())).view([-1, 1]) g.ndata['feat'] = torch.cat([g.ndata['feat'], cc], dim=1) return dataset
def dgl_to_nx(graph, edge_map): # find better way to do this..want to be able to launch without torch installed import torch import dgl g = dgl.to_networkx(graph, edge_attrs=['one_hot']) edge_map_r = {v: k for k, v in edge_map.items()} nx.set_edge_attributes( g, {(n1, n2): edge_map_r[d['one_hot'].item()] for n1, n2, d in g.edges(data=True)}, 'label') return g
def dgl_to_nx(g_dgl, edge_map): hot_to_label = {v: k for k, v in edge_map.items()} print(hot_to_label) hots = g_dgl.edata['one_hot'].detach().numpy() G = dgl.to_networkx(g_dgl) labels = {e: hot_to_label[i] for i, e in zip(hots, G.edges())} print(labels) nx.set_edge_attributes(G, labels, 'label') print(G.nodes()) G = nx.to_undirected(G) return G
def convert_dgl_to_nx(G: dgl.DGLGraph) -> nx.Graph: """ Converts a DGL Graph (``dgl.DGLGraph``) to a NetworkX (``nx.Graph``) object. Preserves node and edge attributes. :param G: ``dgl.DGLGraph`` to convert to ``NetworkX`` graph. :type G: dgl.DGLGraph :return: NetworkX graph object. :rtype: nx.Graph """ node_attrs = G.node_attr_schemes().keys() edge_attrs = G.edge_attr_schemes().keys() return dgl.to_networkx(G, node_attrs, edge_attrs)
def state(self): features = torch.stack([ x for i, x in enumerate(self.dataset.ndata['feat']) if i in self.picked_nodes ]) features = np.array(features) graph = dgl.add_self_loop(self.graph) graph = dgl.to_networkx(graph).to_undirected() self.embedding_model.fit(graph, features) embedding = self.embedding_model.get_embedding() embedding = np.sum(embedding, axis=0) return embedding
def convert_dgl_to_nx(G: dgl.DGLGraph) -> nx.Graph: """ Converts a DGL Graph (dgl.DGLGraph) to a NetworkX (nx.Graph) object. Preservers node and edge attributes. :param G: dgl.DGLGraph to convert to NetworkX :type G: dgl.DGLGraph :return: NetworkX graph object :rtype: nx.Graph """ node_attrs = G.node_attr_schemes().keys() edge_attrs = G.edge_attr_schemes().keys() nx_g = dgl.to_networkx(G, node_attrs, edge_attrs) return nx_g
def process_dataset(name, epsilon): if name == 'cora': dataset = CoraGraphDataset() elif name == 'citeseer': dataset = CiteseerGraphDataset() graph = dataset[0] feat = graph.ndata.pop('feat') label = graph.ndata.pop('label') train_mask = graph.ndata.pop('train_mask') val_mask = graph.ndata.pop('val_mask') test_mask = graph.ndata.pop('test_mask') train_idx = th.nonzero(train_mask, as_tuple=False).squeeze() val_idx = th.nonzero(val_mask, as_tuple=False).squeeze() test_idx = th.nonzero(test_mask, as_tuple=False).squeeze() nx_g = dgl.to_networkx(graph) print('computing ppr') diff_adj = compute_ppr(nx_g, 0.2) print('computing end') if name == 'citeseer': print('additional processing') feat = th.tensor(preprocess_features(feat.numpy())).float() diff_adj[diff_adj < epsilon] = 0 scaler = MinMaxScaler() scaler.fit(diff_adj) diff_adj = scaler.transform(diff_adj) diff_edges = np.nonzero(diff_adj) diff_weight = diff_adj[diff_edges] diff_graph = dgl.graph(diff_edges) graph = graph.add_self_loop() return graph, diff_graph, feat, label, train_idx, val_idx, test_idx, diff_weight
def nx_graph_from_pdb_file(self, pdb_code, chain_selection='all', contact_file=None): """ Produces a NetworkX Graph Object :param pdb_code: 4 character PDB accession code :type pdb_code: str :param chain_selection: string indicating chain selection {'A', 'B', 'AB', ..., 'all'} :type chain_selection: str :param contact_file: Path to GetContacts output file. :type contact_file: str, optional :return: NetworkX graph object of protein """ g, resiude_name_encoder, residue_id_encoder = self.dgl_graph_from_pdb_file( pdb_code, chain_selection, contact_file) node_attrs = g.node_attr_schemes().keys() edge_attrs = g.edge_attr_schemes().keys() return dgl.to_networkx( g, node_attrs, edge_attrs), resiude_name_encoder, residue_id_encoder
def nx_graph_from_pdb_code(self, pdb_code, chain_selection='all', contact_file=None, edge_construction=['contacts'], encoding=False, k_nn=None, custom_edges=None): """ Produces a NetworkX Graph Object :param encoding: :type bool: :param edges: User-supplied edges, defaults to None :type edges: Pandas DataFrame, optional :param pdb_code: 4 character PDB accession code :type pdb_code: str :param chain_selection: string indicating chain selection {'A', 'B', 'AB', ..., 'all'}, defaults to 'all' :type chain_selection: str :param contact_file: Path to GetContacts output file. :type contact_file: str, optional :return: NetworkX graph object of protein :rtype: NetworkX graph """ assert encoding, 'Non-numeric feature encoding must be True' g, resiude_name_encoder, residue_id_encoder = self.dgl_graph_from_pdb_code( pdb_code=pdb_code, chain_selection=chain_selection, contact_file=contact_file, edge_construction=edge_construction, custom_edges=custom_edges, encoding=encoding, k_nn=k_nn) node_attrs = g.node_attr_schemes().keys() edge_attrs = g.edge_attr_schemes().keys() return dgl.to_networkx( g, node_attrs, edge_attrs), resiude_name_encoder, residue_id_encoder
def atest_nx_conversion(index_dtype): # check conversion between networkx and DGLGraph def _check_nx_feature(nxg, nf, ef): # check node and edge feature of nxg # this is used to check to_networkx num_nodes = len(nxg) num_edges = nxg.size() if num_nodes > 0: node_feat = ddict(list) for nid, attr in nxg.nodes(data=True): assert len(attr) == len(nf) for k in nxg.nodes[nid]: node_feat[k].append(F.unsqueeze(attr[k], 0)) for k in node_feat: feat = F.cat(node_feat[k], 0) assert F.allclose(feat, nf[k]) else: assert len(nf) == 0 if num_edges > 0: edge_feat = ddict(lambda: [0] * num_edges) for u, v, attr in nxg.edges(data=True): assert len(attr) == len(ef) + 1 # extra id eid = attr['id'] for k in ef: edge_feat[k][eid] = F.unsqueeze(attr[k], 0) for k in edge_feat: feat = F.cat(edge_feat[k], 0) assert F.allclose(feat, ef[k]) else: assert len(ef) == 0 n1 = F.randn((5, 3)) n2 = F.randn((5, 10)) n3 = F.randn((5, 4)) e1 = F.randn((4, 5)) e2 = F.randn((4, 7)) g = dgl.graph([(0, 2), (1, 4), (3, 0), (4, 3)], index_dtype=index_dtype) g.ndata.update({'n1': n1, 'n2': n2, 'n3': n3}) g.edata.update({'e1': e1, 'e2': e2}) # convert to networkx nxg = dgl.to_networkx(g, node_attrs=['n1', 'n3'], edge_attrs=['e1', 'e2']) assert len(nxg) == 5 assert nxg.size() == 4 _check_nx_feature(nxg, {'n1': n1, 'n3': n3}, {'e1': e1, 'e2': e2}) # convert to DGLGraph, nx graph has id in edge feature # use id feature to test non-tensor copy g = dgl.graph(nxg, node_attrs=['n1'], edge_attrs=['e1', 'id'], index_dtype=index_dtype) assert g._idtype_str == index_dtype # check graph size assert g.number_of_nodes() == 5 assert g.number_of_edges() == 4 # check number of features # test with existing dglgraph (so existing features should be cleared) assert len(g.ndata) == 1 assert len(g.edata) == 2 # check feature values assert F.allclose(g.ndata['n1'], n1) # with id in nx edge feature, e1 should follow original order assert F.allclose(g.edata['e1'], e1) assert F.array_equal(g.edata['id'], F.copy_to(F.arange(0, 4), F.cpu())) # test conversion after modifying DGLGraph # TODO(minjie): enable after mutation is supported #g.pop_e_repr('id') # pop id so we don't need to provide id when adding edges #new_n = F.randn((2, 3)) #new_e = F.randn((3, 5)) #g.add_nodes(2, data={'n1': new_n}) ## add three edges, one is a multi-edge #g.add_edges([3, 6, 0], [4, 5, 2], data={'e1': new_e}) #n1 = F.cat((n1, new_n), 0) #e1 = F.cat((e1, new_e), 0) ## convert to networkx again #nxg = g.to_networkx(node_attrs=['n1'], edge_attrs=['e1']) #assert len(nxg) == 7 #assert nxg.size() == 7 #_check_nx_feature(nxg, {'n1': n1}, {'e1': e1}) # now test convert from networkx without id in edge feature # first pop id in edge feature for _, _, attr in nxg.edges(data=True): attr.pop('id') # test with a new graph g = dgl.graph(nxg, node_attrs=['n1'], edge_attrs=['e1']) # check graph size assert g.number_of_nodes() == 5 assert g.number_of_edges() == 4 # check number of features assert len(g.ndata) == 1 assert len(g.edata) == 1 # check feature values assert F.allclose(g.ndata['n1'], n1) # edge feature order follows nxg.edges() edge_feat = [] for _, _, attr in nxg.edges(data=True): edge_feat.append(F.unsqueeze(attr['e1'], 0)) edge_feat = F.cat(edge_feat, 0) assert F.allclose(g.edata['e1'], edge_feat) # Test converting from a networkx graph whose nodes are # not labeled with consecutive-integers. nxg = nx.cycle_graph(5) nxg.remove_nodes_from([0, 4]) for u in nxg.nodes(): nxg.nodes[u]['h'] = F.tensor([u]) for u, v, d in nxg.edges(data=True): d['h'] = F.tensor([u, v]) g = dgl.DGLGraph() g.from_networkx(nxg, node_attrs=['h'], edge_attrs=['h']) assert g.number_of_nodes() == 3 assert g.number_of_edges() == 4 assert g.has_edge_between(0, 1) assert g.has_edge_between(1, 2) assert F.allclose(g.ndata['h'], F.tensor([[1.], [2.], [3.]])) assert F.allclose(g.edata['h'], F.tensor([[1., 2.], [1., 2.], [2., 3.], [2., 3.]]))
action='store_true', default=True, help="indicates whether to use early stop or not") parser.add_argument('--fastmode', action="store_true", default=False, help="skip re-evaluate the validation set") args = parser.parse_args() data = CoraGraphDataset() dataset = data[0] dataset = dgl.add_self_loop(dataset) embedding_model = TENE() embedding_model.fit( dgl.to_networkx(dataset).to_undirected(), np.array(dataset.ndata['feat'])) dataset_embedding = embedding_model.get_embedding() dataset_embedding = np.sum(dataset_embedding, axis=0) heads = ([args.num_heads] * args.num_layers) + [args.num_out_heads] GNN_model = GAT(args.num_layers, dataset.ndata['feat'].shape[1], args.num_hidden, data.num_labels, heads, F.elu, args.in_drop, args.attn_drop, args.negative_slope, args.residual) GNN_model.load_state_dict(torch.load('GAT/es_checkpoint.pt')) env = myenv(GNN_model, embedding_model, dataset) env.reset() # if gpu is to be used device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
def plot_graph(graph, path): nx_graph = dgl.to_networkx(graph) pos = nx.kamada_kawai_layout(nx_graph) nx.draw(nx_graph, pos, with_labels=True, node_color=[[.7, .7, .7]]) plt.savefig(path) plt.close()
import numpy as np import networkx as nx from karateclub.node_embedding.attributed import TENE import dgl from dgl.data import CoraGraphDataset data = CoraGraphDataset() g = data[0] g = dgl.add_self_loop( dgl.node_subgraph(g, list(set(np.random.choice(len(g.nodes()), 5))))) X = np.array(g.ndata['feat']) g = dgl.to_networkx(g).to_undirected() # g = nx.newman_watts_strogatz_graph(200, 20, 0.05) # # X = np.random.uniform(0, 1, (200, 200)) model = TENE() model.fit(g, X) embedding = model.get_embedding() embedding = np.sum(embedding, axis=0) # print(np.concatenate((embedding, embedding), axis=0).shape) print(embedding.shape)
def visualize_sub_graph(sub_graph, edge_weights=None, origin_nodes=None, center_node=None): """ Use networkx to visualize the sub_graph and, if edge weights are given, set edges with different fading of blue. Parameters ---------- sub_graph: DGLGraph, the sub_graph to be visualized. edge_weights: Tensor, the same number of edges. Values are (0,1), default is None origin_nodes: List, list of node ids that will be used to replace the node ids in the subgraph in visualization center_node: Tensor, the node id in origin node list to be highlighted with different color Returns show the sub_graph ------- """ # Extract original idx and map to the new networkx graph # Convert to networkx graph g = dgl.to_networkx(sub_graph) nx_edges = g.edges(data=True) if not (origin_nodes is None): n_mapping = { new_id: old_id for new_id, old_id in enumerate(origin_nodes.tolist()) } g = nx.relabel_nodes(g, mapping=n_mapping) pos = nx.spring_layout(g) if edge_weights is None: options = { "node_size": 1000, "alpha": 0.9, "font_size": 24, "width": 4, } else: ec = [edge_weights[e[2]['id']][0] for e in nx_edges] options = { "node_size": 1000, "alpha": 0.3, "font_size": 12, "edge_color": ec, "width": 4, "edge_cmap": plt.cm.Reds, "edge_vmin": 0, "edge_vmax": 1, "connectionstyle": "arc3,rad=0.1" } nx.draw(g, pos, with_labels=True, node_color='b', **options) if not (center_node is None): nx.draw(g, pos, nodelist=center_node.tolist(), with_labels=True, node_color='r', **options) plt.show()
import dgl from dgl.data import CoraGraphDataset, CiteseerGraphDataset, PubmedGraphDataset import networkx as nx import torch import torch.nn.functional as F import numpy as np from GAT.model import GAT data = CoraGraphDataset() dataset = data[0] picked_nodes = list(set(np.random.choice(dataset.nodes().numpy(), 200))) graph = dgl.node_subgraph(dataset, picked_nodes) graph = dgl.add_self_loop(graph) features = torch.stack( [x for i, x in enumerate(dataset.ndata['feat']) if i in picked_nodes]) g = dgl.to_networkx(graph) f = np.array(dataset.ndata['feat']) print("*************") print(graph.edata['_ID']) parser = argparse.ArgumentParser(description='GAT') parser.add_argument("--gpu", type=int, default=0, help="which GPU to use. Set -1 to use CPU.") parser.add_argument("--epochs", type=int, default=500, help="number of training epochs") parser.add_argument("--num-heads", type=int,
def visualize_wind_farm(g: dgl.DGLGraph, min_distance: float, angle_threshold: float, wind_direction: float, wind_speed: float, x_grid_size: float, y_grid_size: float, dir_mark_margin=0.01, dir_mark_len=0.03, arrow_size=0.01, viz_eps=0.02, dpi=250, label_size=15, tick_size=12, annotation_size=12, show_color_bar_label=False, edge_width=2.0, legend_size=15): # Figure drawing parameters influential_region_zorder = -1 min_distance_region_zorder = 0 edge_zorder = 2 turbine_zorder = 3 scatter_line_width = 2.0 scatter_ball_size = 200 x_limit = x_grid_size y_limit = y_grid_size fig, (ax, ax_colorbar) = plt.subplots(1, 2, figsize=(10.5, 10), gridspec_kw={'width_ratios': [10, 0.5]}, dpi=dpi) fig.tight_layout(rect=[0, 0.03, 1, 0.95]) ax.xaxis.grid(True, which='major') ax.xaxis.grid(True, which='minor') ax.yaxis.grid(True, which='major') ax.yaxis.grid(True, which='minor') ax.set_xlim([-x_limit * viz_eps, x_limit * (1 + viz_eps)]) ax.set_ylim([-y_limit * viz_eps, y_limit * (1 + viz_eps)]) ax.tick_params(labelsize=tick_size) # Draw turbines color-coded with powers x, y = g.ndata['x'], g.ndata['y'] cmap = matplotlib.cm.Blues norm = matplotlib.colors.Normalize(vmin=0.0, vmax=1.0) turbine_scatter = ax.scatter(x, y, label='Turbine', cmap=cmap, c=norm(g.ndata['power']), edgecolors='#bbbbbb', linewidths=scatter_line_width, s=scatter_ball_size, zorder=turbine_zorder) # Draw interaction edges xys = torch.cat([x, y], dim=-1).squeeze().numpy() pos_dict = {} for i, xy in enumerate(xys): pos_dict[i] = xy nxg = dgl.to_networkx(g) nx.draw_networkx_edges(nxg, edge_color='grey', ax=ax, width=edge_width, pos=pos_dict) ax.set_xlabel("Wind farm X size (m)", fontsize=label_size) ax.set_ylabel("Wind farm Y size (m)", fontsize=label_size) cbar = fig.colorbar(turbine_scatter, cax=ax_colorbar, ticks=np.arange(0.0, 1.1, 0.05)) if show_color_bar_label: cbar.set_label('Power', fontsize=label_size) cbar.set_clim(0.0, 1.0) cbar.ax.tick_params(labelsize=tick_size) for i, (x, y) in enumerate(zip(g.ndata['x'], g.ndata['y'])): # Add min-distance circle circle = plt.Circle((x, y), min_distance / 2, hatch='....', facecolor='white', edgecolor='#ffa45c', alpha=1.0, zorder=min_distance_region_zorder) # Add annotation for depicting turbine index and the corresponding power ax.annotate("T{}".format(i + 1), xy=(x, y + y_limit * 0.025), fontsize=annotation_size, horizontalalignment="center") # ax.annotate("Power : {:.2f}".format(index_power_dict[node.index]), # (x, y - y_limit * viz_eps)) ax.add_artist(circle) # Add influential cones wedge = Wedge( (x, y), np.sqrt(x_grid_size**2 + y_grid_size**2), # radius 270 - wind_direction - angle_threshold, # from theta 1 (in degrees) # FLORIS 1.4 measures 270 degree as left 270 - wind_direction + angle_threshold, # to theta 2 (in degrees) color='g', alpha=0.05, zorder=influential_region_zorder) ax.add_patch(wedge) # Draw directional mark dir_mark_center_x = x_limit * (1 - 2 * dir_mark_margin - dir_mark_len) dir_mark_center_y = y_limit * (1 - 2 * dir_mark_margin - dir_mark_len) marker_len = x_limit * dir_mark_len # WEST dir_mark_west_x = dir_mark_center_x - marker_len dir_mark_west_y = dir_mark_center_y # EAST dir_mark_east_x = dir_mark_center_x + marker_len dir_mark_east_y = dir_mark_center_y # NORTH dir_mark_north_x = dir_mark_center_x dir_mark_north_y = dir_mark_center_y + marker_len # SOUTH dir_mark_south_x = dir_mark_center_x dir_mark_south_y = dir_mark_center_y - marker_len # Visualize wind direction # Compass compass_color = 'k' wd_color = 'orange' arrow_size = x_limit * arrow_size # WEST -> EAST w2e = Line2D((dir_mark_west_x, dir_mark_east_x), (dir_mark_west_y, dir_mark_east_y), alpha=0.5, c=compass_color) ax.add_line(w2e) # NORTH -> SOUTH n2s = Line2D((dir_mark_north_x, dir_mark_south_x), (dir_mark_north_y, dir_mark_south_y), alpha=0.5, c=compass_color) ax.add_line(n2s) # NORTH -> WEST n2w = Line2D((dir_mark_north_x, dir_mark_west_x), (dir_mark_north_y, dir_mark_west_y), alpha=0.5, c=compass_color) ax.add_line(n2w) # draw wind direction arrow wind_dir_rad = np.radians(wind_direction - 270) sin = np.sin(wind_dir_rad) cos = np.cos(wind_dir_rad) wind_start_x = dir_mark_center_x - marker_len * cos # tail wind_start_y = dir_mark_center_y + marker_len * sin wind_end_x = dir_mark_center_x + marker_len * cos # arrow wind_end_y = dir_mark_center_y - marker_len * sin ax.arrow(wind_start_x, wind_start_y, wind_end_x - wind_start_x, wind_end_y - wind_start_y, linewidth=2, head_width=arrow_size, head_length=arrow_size, fc=wd_color, ec=wd_color, length_includes_head=True, zorder=edge_zorder) ax.annotate("Wind direction : {}$^\circ$".format(wind_direction), (dir_mark_west_x - marker_len * 7.0, dir_mark_center_y + marker_len * 0.5)) ax.annotate("Wind speed : {} m/s".format(wind_speed), (dir_mark_west_x - marker_len * 7.0, dir_mark_center_y - marker_len * 0.5)) handles, labels = ax.get_legend_handles_labels() handles += [wedge, circle] labels += ["influential region", "min. distance"] ax.legend(handles, labels, prop={'size': legend_size})