def addGraphPretty(model, ax, \ positions = None, \ cmap = cm.tab20, **kwargs): from matplotlib.patches import FancyArrowPatch, Circle, ConnectionStyle, Wedge r = .115 # radius for circle graph = model.graph if positions is None: positions = nx.circular_layout(graph) # colors = cm.tab20(arange(model.nNodes)) # colors = cm.get_cmap('tab20')(arange(model.nNodes)) if graph.number_of_nodes() > 20: cmap = cm.get_cmap('gist_rainbow') colors = cmap(arange(model.nNodes)) # DEFAULTS circlekwargs = dict(\ radius = r, \ alpha = 1, \ edgecolor = 'black', \ linewidth = 1, \ linestyle = 'solid',\ zorder = 2) for k, v in kwargs.get('circle', {}).items(): circlekwargs[k] = v annotatekwargs = dict(\ horizontalalignment = 'center', \ verticalalignment = 'center', \ transform = ax.transAxes, \ fontsize = 12,\ ) for k, v in kwargs.get('annotate', {}).items(): annotatekwargs[k] = v for n in graph: # make circle c = Circle(positions[n], facecolor = colors[model.mapping[n]],\ **circlekwargs) # add label # print(c.center[:2], pos[n]) # ax.text(*c.center, n, horizontalalignment = 'center', \ # verticalalignment = 'center', transform = ax.transAxes) annotatekwargs['fontsize'] = .95 * circlekwargs['radius'] ax.annotate(n, c.center, **annotatekwargs) # add to ax ax.add_patch(c) # TODO : remove tis for member assignment # bookkeep for adding edge graph.node[n]['patch'] = c seen = {} # bookkeeping from copy import copy # arrow style for drawing arrowsprops = dict(\ arrowstyle = '-|>' if graph.is_directed() else '<|-|>' ,\ mutation_scale = 15.0,\ lw = 2,\ alpha = 1,\ ) edgesScaling = {(u, v): graph[u][v]['weight'] for u, v in graph.edges()} minWeight, maxWeight = min(edgesScaling.values()), max( edgesScaling.values()) for u, v in graph.edges(): n1 = graph.node[u]['patch'] n2 = graph.node[v]['patch'] d = graph[u][v]['weight'] rad = 0.1 if (u, v) in seen: rad = seen.get((u, v)) rad = (rad + np.sign(rad) * 0.1) * -1 # set properties of the edge alphaEdge = clip(abs(d), .2, 1) arrowsprops['color'] = 'green' if d > 0 else 'red' # arrowsprops['alpha'] = alphaEdge arrowsprops['lw'] = ((d - minWeight) / (maxWeight - minWeight)) * 5 # self-edge is a special case if u == v: n2 = copy(n1) n1 = copy(n1) theta = random.uniform(0, 2 * pi) rotation = pi corner1 = array([sin(theta), cos(theta)]) * r corner2 = array([sin(theta + rotation), cos(theta + rotation)]) *\ r + .12 * sign(random.randn()) * r n1.center = array(n1.center) + corner1 n2.center = array(n2.center) + corner2 # n1.center = (n1.center[0] + r, n1.center[1] ) # n2.center = (n2.center[0] - r, n2.center[1]) rad = radians(135) # trial and error # add edge e = FancyArrowPatch(n2.center, n1.center, **arrowsprops) e.set_arrowstyle(head_length=head_length) else: e = FancyArrowPatch(n1.center,n2.center, patchA = n1, patchB = n2,\ connectionstyle = f'arc3,rad={rad}', **arrowsprops) seen[(u, v)] = rad ax.add_patch(e) ax.autoscale() ax.set_aspect('equal') return ax
def showGraph(graph, attr='weight'): ''' Shows the adjacency matrix and the 'graphical layout' ''' # TODO: add curved arreas # TODO: plot add zeros # ugly af # style.use('seaborn-white') fig, axes = subplots(1, 2) u = unique(list(nx.get_edge_attributes(graph, attr).values())) cmap = cm.get_cmap('viridis') # cmap = cm.get_cmap('viridis')(linspace(-1, 1, 20)) # cmap[0,:] = 0 # cmap.set_over('DarkViolet') # adjacency plot adj = nx.adjacency_matrix(graph, weight='weight').todense() # adj = (adj - adj.min()) / (adj.max() - adj.min()) # adj[adj == 0] = nan cmap.set_bad('gray', .2) h = axes[0].imshow(\ adj, aspect = 'auto',\ cmap = cmap,\ ) cbar = colorbar(h, ax=axes[0], pad=.01) text(1.15, .5 , 'weight', rotation = 90,\ horizontalalignment='center', \ fontsize = 20,\ transform = axes[0].transAxes) cbar.set_ticks([round(min(u), 2), round(max(u), 2)]) x = arange(len(graph.nodes())) axes[0].set_xticks(x) axes[0].set_xticklabels(graph.nodes(), ha='center', va='top', minor=False) axes[0].set_yticks(x) axes[0].set_yticklabels(graph.nodes(), ha='center', minor=False) axes[0].tick_params(axis='y', which='major', pad=35) # cbar.set_ticklabels([]) setp(axes[0], **dict(xlabel='node', ylabel='node')) fig.autofmt_xdate() # slant overlapping labels # there probably is a wrapper keyword for this.... from matplotlib.patches import FancyArrowPatch, Circle, ConnectionStyle # graphical layout edges = nx.get_edge_attributes(graph, 'weight') negatives = {} positives = {} maxWeight = max(list(edges.values())) for key, value in edges.items(): value = round(value, 3) edges[key] = value if value < 0: negatives[key] = value else: positives[key] = value r = 2 pos = nx.circular_layout(graph, scale=20) for n in graph: c=Circle(positions[n], radius=r,alpha=1, facecolor = 'white',\ edgecolor = 'black', linewidth = 1, linestyle = 'solid') text(*c.center, n, horizontalalignment='center', verticalalignment='center') axes[1].add_patch(c) graph.node[n]['patch'] = c x, y = positions[n] # pos = nx.circular_layout(graph, scale = .5) # tmp = nx.get_edge_attributes(graph, 'weight') # tmp = {key: abs(value) for key, value in tmp.items()} # nx.set_edge_attributes(graph, tmp, 'absweight') # pos = nx.kamada_kawai_layout(graph, weight= 'absweight', scale= 100000) # patches = nx.draw_networkx_nodes(graph, pos = pos, alpha = 1, node_size = 1500, edgecolors = 'black', node_color = 'white') seen = {} from copy import copy for u, v in graph.edges(): n1 = graph.node[u]['patch'] n2 = graph.node[v]['patch'] d = graph[u][v]['weight'] rad = 0.1 if (u, v) in seen: rad = seen.get((u, v)) rad = (rad + np.sign(rad) * 0.1) * -1 print(u, v) if u == v: j = .1 n2 = copy(n1) n1 = copy(n1) n1.center = (n1.center[0] + r, n1.center[1]) n2.center = (n2.center[0] - r, n2.center[1]) # n1.center = tuple(i - j for i in n1.center) # n2.center = tuple(i + j for i in n2.center) print(n1, n2) rad = 1.6 print(n1.center, n2.center) e = FancyArrowPatch(n2.center, n1.center, connectionstyle = f'arc3,rad={rad}',\ arrowstyle = '-|>',\ mutation_scale = 10.0, lw = 2, alpha = abs(d), color = 'red' if d < 0 else 'green') e.set_arrowstyle(arrowstyle='-|>', head_length=1.5) else: connectionstyle = f'arc3,rad={rad}' e = FancyArrowPatch(n1.center,n2.center, patchA = n1, patchB = n2,\ arrowstyle = '->', connectionstyle = connectionstyle, mutation_scale = 10.0, lw=2, alpha= abs(d), color= 'red' if d < 0 else 'green') # if (u,v) not in seen: # center = (n1.center + n2.center) / 2 + random.rand() # text(*center, round(d,2)) seen[(u, v)] = rad axes[1].add_patch(e) # nx.draw_networkx_labels(graph, pos = pos,\ # node_labels = graph.nodes()) # # nx.draw_networkx_edges(graph, # pos, # edgelist = negatives, # width = list(negatives.values()), edge_color = 'red', # edge_labels = negatives, ax = axes[-1]) # nx.draw_networkx_edges(graph, # pos, # edgelist = positives, # width = list(positives.values()), edge_color = 'green', # edge_labels = positives, ax = axes[-1] # ) # nx.draw_networkx_edge_labels(graph, pos, edge_labels = edges, ax = axes[-1], label_pos = .5) axes[-1].autoscale() axes[-1].axis('off')