def isochrones_subfig( fig_: Figure, x_: np.ndarray, y_: np.ndarray, color_: str = gray_ ) -> Tuple[Axes, Tuple[float, float]]: r"""Generate an isochrones subfig for embedding.""" # Top left isochrones 0 size_zoom_0: Tuple[float, float] = (0.65, 0.55) posn_0: Tuple[float, float] = (0.0, 0.75) axes_0 = fig_.add_axes([*posn_0, *size_zoom_0]) plt.axis("off") n_isochrones = 6 for i_, sf_ in enumerate(np.linspace(0.5, 1.2, n_isochrones)): plt.plot( *(x_, sf_ * y_), "-", color=self.gray_color(i_, n_gray), lw=2.5, ) plt.xlim(0, 1) plt.ylim(0, 1) sf1_ = 1.3 sf2_ = 1.3 arrow_xy_: np.ndarray = np.array([0.2, 0.8]) arrow_dxy_: np.ndarray = np.array([-0.025, 0.15]) motion_xy_: Tuple[float, float] = (0.1, 0.8) motion_angle_ = 23 my_arrow_style = ArrowStyle.Simple( head_length=1 * sf1_, head_width=1 * sf1_, tail_width=0.1 * sf1_ ) axes_0.annotate( "", xy=arrow_xy_, xytext=arrow_xy_ + arrow_dxy_ * sf2_, transform=axes_0.transAxes, arrowprops=dict(arrowstyle=my_arrow_style, color=color_, lw=3), ) plt.text( *motion_xy_, "motion", color=color_, fontsize=16, rotation=motion_angle_, transform=axes_0.transAxes, horizontalalignment="center", verticalalignment="center", ) return (axes_0, posn_0)
def _visualize(self, filename=None, transparent=True): env = self.env fig, ax = plt.subplots(1) [p.remove() for p in reversed(ax.patches)] # Draw boundaries plt.plot([0, 0], [-10, 10], linewidth=5, color='k') plt.plot([9, 9], [-10, 10], linewidth=5, color='k') plt.axis('square') plt.axis('off') plt.xlim((-1, 10)) plt.ylim((-6, 5)) # Car # Pose of the end of the car car = env.x.copy() car = Rectangle((car[0], car[1]), 0.3, env.car_length, angle=np.rad2deg(env.angle), color=colors[-1]) plt.gca().add_patch(car) # pedestrians pedestrians = env.pedestrians pedestrian_angles = self.weighted_directions pedestrian_directions = self.weighted_directions * 5.0 angles = self.expected_angles belief = self.belief for i in range(len(pedestrians)): ped = Circle(pedestrians[i], radius=0.2, color=colors[i], zorder=20) plt.gca().add_patch(ped) style = ArrowStyle.Simple(head_length=1, head_width=1, tail_width=1) xy = pedestrians[i] for j in range(3): dxdy = get_pedestrian_directions(self.pedestrian_speeds[i], angles[i, j])[0] * 5.0 arrow = Arrow(xy[0], xy[1], dxdy[0], dxdy[1], color=colors[i], linewidth=0, width=0.3, alpha=belief[i, j], fill=True) # print(belief[i,j]) # arrow = FancyArrowPatch(posA=xy, posB=xy+dxdy, arrowstyle='simple', color=colors[i], alpha=belief[i, j], linewidth=1.0) plt.gca().add_patch(arrow) arrow = Arrow( xy[0], xy[1], dxdy[0], dxdy[1], edgecolor=colors[i], width=0.3, linewidth=0.5, fill=False, ) plt.gca().add_patch(arrow) if filename is not None: plt.savefig(filename, bbox_inches='tight', transparent=transparent)
def draw_network(network, nsize="total-degree", ncolor="group", nshape="o", nborder_color="k", nborder_width=0.5, esize=1., ecolor="k", ealpha=0.5, max_nsize=5., max_esize=2., curved_edges=False, threshold=0.5, decimate=None, spatial=True, restrict_sources=None, restrict_targets=None, show_environment=True, fast=False, size=(600, 600), xlims=None, ylims=None, dpi=75, axis=None, show=False, **kwargs): ''' Draw a given graph/network. Parameters ---------- network : :class:`~nngt.Graph` or subclass The graph/network to plot. nsize : float, array of float or string, optional (default: "total-degree") Size of the nodes as a percentage of the canvas length. Otherwise, it can be a string that correlates the size to a node attribute among "in/out/total-degree", or "betweenness". ncolor : float, array of floats or string, optional (default: 0.5) Color of the nodes; if a float in [0, 1], position of the color in the current palette, otherwise a string that correlates the color to a node attribute among "in/out/total-degree", "betweenness" or "group". nshape : char or array of chars, optional (default: "o") Shape of the nodes (see `Matplotlib markers <http://matplotlib.org/api/ markers_api.html?highlight=marker#module-matplotlib.markers>`_). nborder_color : char, float or array, optional (default: "k") Color of the node's border using predefined `Matplotlib colors <http://matplotlib.org/api/colors_api.html?highlight=color #module-matplotlib.colors>`_). or floats in [0, 1] defining the position in the palette. nborder_width : float or array of floats, optional (default: 0.5) Width of the border in percent of canvas size. esize : float, str, or array of floats, optional (default: 0.5) Width of the edges in percent of canvas length. Available string values are "betweenness" and "weight". ecolor : str, char, float or array, optional (default: "k") Edge color. If ecolor="group", edges color will depend on the source and target groups, i.e. only edges from and toward same groups will have the same color. max_esize : float, optional (default: 5.) If a custom property is entered as `esize`, this normalizes the edge width between 0. and `max_esize`. decimate : int, optional (default: keep all connections) Plot only one connection every `decimate`. spatial : bool, optional (default: True) If True, use the neurons' positions to draw them. restrict_sources : str or list, optional (default: all) Only draw edges starting from a restricted set of source nodes. restrict_targets : str or list, optional (default: all) Only draw edges ending on a restricted set of target nodes. show_environment : bool, optional (default: True) Plot the environment if the graph is spatial. fast : bool, optional (default: False) Use a faster algorithm to plot the edges. This method leads to less pretty plots and zooming on the graph will make the edges start or ending in places that will differ more or less strongly from the actual node positions. size : tuple of ints, optional (default: (600,600)) (width, height) tuple for the canvas size (in px). dpi : int, optional (default: 75) Resolution (dot per inch). show : bool, optional (default: True) Display the plot immediately. ''' import matplotlib.pyplot as plt size_inches = (size[0] / float(dpi), size[1] / float(dpi)) if axis is None: fig = plt.figure(facecolor='white', figsize=size_inches, dpi=dpi) axis = fig.add_subplot(111, frameon=0, aspect=1) axis.set_axis_off() pos, layout = None, None # restrict sources and targets if nonstring_container(restrict_sources): if isinstance(restrict_sources[0], str): assert network.is_network(), \ "`restrict_sources` canbe string only for Network." sources = [] for name in restrict_sources: sources.extend(network.population[name].ids) restrict_sources = sources elif isinstance(restrict_sources, str): assert network.is_network(), \ "`restrict_sources` canbe string only for Network." restrict_sources = network.population[restrict_sources].ids if nonstring_container(restrict_targets): if isinstance(restrict_targets[0], str): assert network.is_network(), \ "`restrict_targets` canbe string only for Network." targets = [] for name in restrict_targets: targets.extend(network.population[name].ids) restrict_targets = targets elif isinstance(restrict_targets, str): assert network.is_network(), \ "`restrict_sources` canbe string only for Network." restrict_targets = network.population[restrict_targets].ids # get nodes and edges n = network.node_nb() adj_mat = network.adjacency_matrix(weights=None) if restrict_sources is not None: adj_mat = adj_mat[restrict_sources, :] if restrict_targets is not None: adj_mat = adj_mat[:, restrict_targets] e = adj_mat.nnz # compute properties decimate = 1 if decimate is None else decimate if isinstance(nsize, str): if e: nsize = _node_size(network, nsize) nsize *= max_nsize else: nsize = np.ones(n, dtype=float) elif isinstance(nsize, float): nsize = np.repeat(nsize, n) nsize *= 0.01 * size[0] if isinstance(esize, str) and e: esize = _edge_size(network, esize) esize *= max_esize esize[esize < threshold] = 0. #~ elif isinstance(esize, float): #~ esize = np.repeat(esize, e) esize *= 0.005 * size[0] # border on each side (so 0.5 %) ncolor = _node_color(network, ncolor) c = ncolor if not nonstring_container(nborder_color): nborder_color = np.repeat(nborder_color, n) # check edge color group_based = False if isinstance(ecolor, float): ecolor = np.repeat(ecolor, e) elif ecolor == "groups" and network.is_network(): group_based = True c = np.linspace(0, 1, len(network.population)) ecolor = {} for i, src in enumerate(network.population): idx1 = network.population[src].ids[0] for j, tgt in enumerate(network.population): idx2 = network.population[tgt].ids[0] if src == tgt: ecolor[(src, tgt)] = ncolor[idx1] else: ecolor[(src, tgt)] = \ np.abs(0.8*ncolor[idx1] - 0.2*ncolor[idx2]) # draw pos = np.zeros((n, 2)) if spatial and network.is_spatial(): if show_environment: nngt.geometry.plot.plot_shape(network.shape, axis=axis, show=False) pos = network.get_positions() else: pos[:, 0] = size[0] * (np.random.uniform(size=n) - 0.5) pos[:, 1] = size[1] * (np.random.uniform(size=n) - 0.5) # make nodes nodes = [] if network.is_network(): for group in network.population.values(): idx = group.ids if nonstring_container(ncolor): c = palette(ncolor[idx[0]]) for i in idx: nodes.append( Circle(pos[i], 0.5 * nsize[i], fc=c, ec=nborder_color[i])) else: if not isinstance(c, str): c = palette(ncolor) for i in range(n): nodes.append( Circle(pos[i], 0.5 * nsize[i], fc=c, ec=nborder_color[i])) nodes = PatchCollection(nodes, match_original=True) nodes.set_zorder(2) axis.add_collection(nodes) _set_ax_lim(axis, pos[:, 0], pos[:, 1], xlims, ylims) # use quiver to draw the edges if e: adj_mat = network.adjacency_matrix(weights=None) avg_size = np.average(nsize) arr_style = ArrowStyle.Simple(head_length=0.15 * avg_size, head_width=0.1 * avg_size, tail_width=0.05 * avg_size) arrows = [] if group_based: for src_name, src_group in network.population.items(): for tgt_name, tgt_group in network.population.items(): s_ids = src_group.ids if restrict_sources is not None: s_ids = list(set(restrict_sources).intersection(s_ids)) t_ids = tgt_group.ids if restrict_targets is not None: t_ids = list(set(restrict_targets).intersection(t_ids)) if t_ids and s_ids: s_min, s_max = np.min(s_ids), np.max(s_ids) + 1 t_min, t_max = np.min(t_ids), np.max(t_ids) + 1 edges = np.array(adj_mat[s_min:s_max, t_min:t_max].nonzero(), dtype=int) edges[0, :] += s_min edges[1, :] += t_min if nonstring_container(esize): keep = (esize > 0) edges = edges[:, keep] esize = esize[keep] if decimate > 1: edges = edges[:, ::decimate] if nonstring_container(esize): esize = esize[::decimate] # plot ec = palette(ecolor[(src_name, tgt_name)]) if fast: dl = 0.5 * np.max(nsize) arrow_x = pos[edges[1], 0] - pos[edges[0], 0] arrow_x -= np.sign(arrow_x) * dl arrow_y = pos[edges[1], 1] - pos[edges[0], 1] arrow_x -= np.sign(arrow_y) * dl axis.quiver(pos[edges[0], 0], pos[edges[0], 1], arrow_x, arrow_y, scale_units='xy', angles='xy', scale=1, alpha=0.5, width=1.5e-3, linewidths=0.5 * esize, edgecolors=ec, zorder=1) else: for s, t in zip(edges[0], edges[1]): xs, ys = pos[s, 0], pos[s, 1] xt, yt = pos[t, 0], pos[t, 1] dl = 0.5 * nsize[t] dx = xt - xs dx -= np.sign(dx) * dl dy = yt - ys dy -= np.sign(dy) * dl if curved_edges: arrow = FancyArrowPatch( posA=(xs, ys), posB=(xt, yt), arrowstyle=arr_style, connectionstyle='arc3,rad=0.1', alpha=ealpha, fc=ec, lw=0.5) axis.add_patch(arrow) else: arrows.append( FancyArrow(xs, ys, dx, dy, width=0.3 * avg_size, head_length=0.7 * avg_size, head_width=0.7 * avg_size, length_includes_head=True, alpha=ealpha, fc=ec, lw=0.5)) else: edges = np.array(adj_mat.nonzero(), dtype=int) s_min, s_max, t_min, t_max = 0, n, 0, n if restrict_sources is not None: s_min = np.min(restrict_sources) s_max = np.min(np.max(restrict_sources) + 1, n) if restrict_targets is not None: t_min = np.min(restrict_targets) t_max = np.min(np.max(restrict_targets) + 1, n) edges = np.array(adj_mat[s_min:s_max, t_min:t_max].nonzero(), dtype=int) edges[0, :] += s_min edges[1, :] += t_min # keep only large edges if nonstring_container(esize): keep = (esize > 0) edges = edges[:, keep] if nonstring_container(ecolor): ecolor = ecolor[keep] esize = esize[keep] if decimate > 1: edges = edges[:, ::decimate] if nonstring_container(esize): esize = esize[::decimate] if nonstring_container(ecolor): ecolor = ecolor[::decimate] if isinstance(ecolor, str): ecolor = [ecolor for i in range(0, e, decimate)] if fast: dl = 0.5 * np.max(nsize) arrow_x = pos[edges[1], 0] - pos[edges[0], 0] arrow_x -= np.sign(arrow_x) * dl arrow_y = pos[edges[1], 1] - pos[edges[0], 1] arrow_x -= np.sign(arrow_y) * dl axis.quiver(pos[edges[0], 0], pos[edges[0], 1], arrow_x, arrow_y, scale_units='xy', angles='xy', scale=1, alpha=0.5, width=1.5e-3, linewidths=0.5 * esize, edgecolors=ecolor, zorder=1) else: for i, (s, t) in enumerate(zip(edges[0], edges[1])): xs, ys = pos[s, 0], pos[s, 1] xt, yt = pos[t, 0], pos[t, 1] if curved_edges: arrow = FancyArrowPatch(posA=(xs, ys), posB=(xt, yt), arrowstyle=arr_style, connectionstyle='arc3,rad=0.1', alpha=ealpha, fc=ecolor[i], lw=0.5) axis.add_patch(arrow) else: dl = 0.5 * nsize[t] dx = xt - xs dx -= np.sign(dx) * dl dy = yt - ys dy -= np.sign(dy) * dl arrows.append( FancyArrow(xs, ys, dx, dy, width=0.3 * avg_size, head_length=0.7 * avg_size, head_width=0.7 * avg_size, length_includes_head=True, alpha=ealpha, fc=ecolor[i], lw=0.5)) if not fast: arrows = PatchCollection(arrows, match_original=True) arrows.set_zorder(1) axis.add_collection(arrows) if kwargs.get('tight', True): plt.tight_layout() plt.subplots_adjust(hspace=0., wspace=0., left=0., right=1., top=1., bottom=0.) if show: plt.show()
def draw_bipartite( weights=None, weight_max=None, ): # if weights is None: # weights = np.array([[1, 19], [10, 10]]) n_node = len(weights) if weight_max is None: weight_max = np.mean(np.sum(weights, 1)) * 2 # weight_max = 20 node_sizes = np.concatenate([np.sum(weights, 1), np.sum(weights, 0)]) G = nx.DiGraph() for i in range(n_node): G.add_node(i, layer=0, count=node_sizes[i]) G.add_node(i + n_node, layer=1, count=node_sizes[i + n_node]) for src in range(n_node): for dst in range(n_node): G.add_weighted_edges_from([(src, dst + n_node, weights[src, dst])]) c_max = 255 cmap = plt.get_cmap('coolwarm', c_max) pos = nx.multipartite_layout(G, subset_key="layer") # plt.figure(figsize=(3, 3)) nx.draw_networkx_nodes(G, pos, nodelist=np.arange(n_node**2), node_size=300 * node_sizes / weight_max, node_color=cmap(node_sizes / weight_max), cmap=cmap, alpha=0.5) wmax = np.amax(weights) for edge, v in G.edges.items(): w = v['weight'] nx.draw_networkx_edges( G, pos, edgelist=[edge], edge_color=cmap(w / weight_max * n_node), width=0, arrowstyle=ArrowStyle.Simple( head_length=w / weight_max * 2.1, head_width=w / weight_max * 1.4, tail_width=w / weight_max * 0.5, ), min_source_margin=wmax / 2 + weight_max * 0.2, min_target_margin=wmax / 2 + weight_max * 0.2, ) edge_weights = {k: '%g' % v['weight'] for k, v in G.edges.items()} nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_weights, label_pos=0.33) node_labels = {k: '%g' % v['count'] for k, v in G.nodes.items()} nx.draw_networkx_labels(G, pos, labels=node_labels) plt.axis("equal") plt.box(False) # plt.show() # print('--') return G, pos