Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
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()
Ejemplo n.º 4
0
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