Beispiel #1
0
def darken(data,amt=0.10,is255=False):
    """Darken a vector of colors by fraction `amt` of current intensity.
    
    Parameters
    ----------
    data : matplotlib colorspec or sequence of colorspecs
        input color(s)

    amt : float, optional
        Percentage by which to darken `r`, `g`, and `b`. `a` remains unchanged
        (Default: 0.10)
        
    Returns
    -------
    numpy.ndarray
        Lightened version of data
    """
    data = colorConverter.to_rgba_array(data)

    new_colors = (1.0-amt)*data
    if is255:
        new_colors = (255*new_colors).round()

    new_colors[:,-1] = data[:,-1]

    return new_colors
Beispiel #2
0
 def __init__(self, idx,  **kw):
     
     self.idx = idx
     
     fwhm = kw.pop( 'fwhm', [] )
     coords = kw.pop( 'coords', [] )
     self.window = kw.pop('window',  SkyApertures.R_OUT_UPLIM )  #NOTE: CONSIDER USING THE FRAME DIMENSIONS AS A GUESS?
     
     super().__init__( [Star(coo=coo, fwhm=fwhm) 
                             for (coo,fwhm) in itt.zip_longest(coords, as_iter(fwhm)) ] )
     #self.star_count = len(self.stars)
     resolution = 50
     self.model = ModelStar( idx, self.window, resolution )
     self.plots = []
     self.annotations = []           #TODO:  AnnotationMixin for ApertureCollection????
     
     psfradii = kw.pop( 'psfradii',   np.tile( fwhm, (2,1) ).T * [0.5, 1.5] )
     skyradii = kw.pop( 'skyradii',   np.tile( self.DEFAUL_SKYRADII, (len(fwhm),1) ) )            #SKY_RADII
     photradii =                      np.tile( fwhm, (1,1) ).T * 2.5
     
     apcoo = np.array( interleave( coords, coords ) )                #each stars has 2 apertures.sky and 2 apertures.psf!!!!
     
     #banner( 'Stars.__init__', bg='magenta' )
     
     orange = colorConverter.to_rgba_array('orangered')         #HACK!
     
     self.apertures = StarApertures( dict(coords=apcoo, 
                                             radii=psfradii, 
                                             ls=':', 
                                             colours=['k','w'],
                                             pickradius=0),
                                         
                                     dict(coords=apcoo, 
                                             radii=photradii,
                                             gc='c',
                                             badcolour=orange),    #FIXME:  keyword translation
                                         
                                     dict(coords=apcoo, 
                                             radii=skyradii,
                                             gc='g' ) )
                     
     
     #self.apertures.psf = ApertureCollection( , 
                                       #**kw)
     #self.photaps = PhotApertures(  )
     #self.apertures.sky = SkyApertures( radii=skyradii, 
                                 #coords=apcoo, 
                                 #**kw )
     
     self.has_plot = 0
Beispiel #3
0
def SpikeCollection(x, y, radius, linewidth=1, color=(1, 1, 0.9), alpha=0.9, gamma=3.33):
  """ returns a LineCollection of spikes.
      example:
      ax = gca()
      c = make_spike(x=[0, 5, -3, 3], y=[0, 2, -1, -5], radius=[10, 5, 5, 8], color=[(1, 1, 0.9), (0, 1, 0)], alpha=0.9)
      ax.add_collection(c)
      x, y, radius needs to be of the same length, otherwise the length of x is taken as the number of points
      color is repeated if it is shorter than the list of x, y radius
      alpha is the maximum alpha in the spike. gamma is used to correct for the buggy matplotlib transparency code
  """
  x = asarray(x).reshape(-1)
  y = asarray(y).reshape(-1)
  radius = asarray(radius).reshape(-1)

  Npoints = x.shape[0]

  alpha0 = 0.05
  Nseg = int(alpha / alpha0)
  alpha0 = alpha / Nseg

  l = linspace(0, 1, Nseg, endpoint=False)
  l **= 1 / gamma

  lines = zeros((Npoints, Nseg * 2, 2, 2))
  lines[:, :Nseg, 0, 1] = (-1 + l)
  lines[:, :Nseg, 1, 1] = (1. - l)

  lines[:, Nseg:, 0, 0] = (-1 + l)
  lines[:, Nseg:, 1, 0] = (1. - l)

  lines[:, :, :, :] *= radius[:, newaxis, newaxis, newaxis]
  lines[:, :, :, 0] += x[:, newaxis, newaxis]
  lines[:, :, :, 1] += y[:, newaxis, newaxis]

  lines.shape = -1, 2, 2

  colors = colorConverter.to_rgba_array(color).repeat(Nseg * 2, axis=0).reshape(-1, Nseg * 2, 4)
# this formular is math trick:
# it ensures the alpha value of the line segment N, when overplot on the previous line segment 0..N-1,
# gives the correct alpha_N = N * alpha0.
# solve (1 - x_N) (N-1) alpha_0 + x_N = N alpha_0
  colors[:, :Nseg, 3] = 1.0 / ( 1. / alpha0 - arange(Nseg))[newaxis, :]
  colors[:, Nseg:, 3] = colors[:, :Nseg, 3]
  colors.shape = -1, 4

  c = LineCollection(lines, linewidth, colors=colors, antialiased=1)
  return c
Beispiel #4
0
def plot_main(args):
    if args.rescale is not None and args.rescale <= 0:
        raise ValueError('expected positive value for rescaling : %d' %
                args.rescale)
    coll = []
    npz = np.load(args.input)
    for arr in ( npz[n] for n in sorted(npz.files) ):
        x, U, P = arr.T
        if args.plot_users:
            y = U
        else:
            y = P
        if args.rescale is not None:
            y = y / y[-args.rescale:].mean()
        coll.append(np.c_[x,y])
    fig = pp.figure()
    ax = pp.axes([0.1, 0.15, 0.85, 0.80])
    lc = LineCollection(coll, 
            colors=colorConverter.to_rgba_array('k' * len(coll), args.alpha))
    ax.add_collection(lc)
    if args.mean:
        coll = np.asarray(coll)
        m = coll[:,::20,1].mean(axis=0)
        spl = splrep(x[::20], m)
        tt = np.linspace(x[0],x[-1], 1000)
        mm = splev(tt, spl)
        ax.plot(tt, mm, 'r-', lw=3)
    pp.axis('tight')
    if args.annotate is not None:
        ym, yM = pp.ylim()
        ys = yM - ym
        xt = args.annotate * .45
        yt = yM + .1 * ys
        ax.text(xt, yt, 'transient', fontsize='small')
        ax.axvspan(0, args.annotate, color='b', alpha=args.alpha/2)
        pp.ylim(ym, yM + .2 * ys)
    pp.xlabel('time (days)')
    if args.rescale is not None:
        pp.ylabel(r'scaled number of users $N_u / \overline{N_u}$')
    else:
        pp.ylabel(r'number of users $N_u$')
    pp.draw()
    if args.output is not None:
        pp.savefig(args.output, format=fmt(args.output.name))
    pp.show()
Beispiel #5
0
def get_rgb255(inp):
    """Fetch `r,g,b` values where `r,g,b` are integers ranging from 0 to 255

    Parameters
    ----------
    inp : *RGB* or *RGBA* sequence or str
        Can be color hex string, like "#007ADF", a matplotlib color letter like "r",
        a matplotlib color name like "black, et c."
        See :meth:`matplotlib.colors.colorConverter.to_rgb`

    Returns
    -------
    :class:`numpy.ndarray`
        Numpy array of `r,g,b` tuples where `r,g,b` take integer values from 0 to 255
    """
    data = colorConverter.to_rgba_array(inp)
    data = (255*data[:,:3]).round().astype(int).ravel()

    return data
Beispiel #6
0
 def __init__(self, axcol='k', fontcol='k', size=(16,12), font='serif'):
     self.axcol = axcol
     self.fontcol = fontcol
     self.size = size
     self.font = font
     
     if axcol == 'w':
         col = colorConverter.to_rgba_array(plt.rcParams['axes.color_cycle'])[:,:-1]
         inv_col = (256-(256*col))/256.0
         plt.rc('axes', color_cycle = list(inv_col))
     
     plt.rc('figure', figsize=size, facecolor='none', edgecolor='none')
     plt.rc('savefig', dpi=300, facecolor='none', edgecolor='none', frameon='False')
     f = {'family':font, 'size':20}
     plt.rc('font', **f)
     plt.rc('text', color=fontcol)
     plt.rc('axes', labelsize='x-large', edgecolor=axcol, labelcolor=fontcol, facecolor='none', linewidth=3)
     plt.rc('xtick', labelsize='large', color=fontcol)
     plt.rc('ytick', labelsize='large', color=fontcol)
     plt.rc('lines', markersize=8, linewidth=2)
Beispiel #7
0
 def __init__(self, idx, window, resolution=None):
     
     banner( 'ModelStar.__init__', bg='green' )
     
     #TODO:  kill idx
     self.idx = idx
     self.window = window
     self.resolution = resolution or window
     
     #self.psf = psf
     coo = [( window/2, window/2 )]
     wslice = (slice(0, window),)*2
     
     super().__init__( coo=coo[0], 
                       slice=wslice,
                       sky_mean=0 )      #won't calculate rprofile as no image kw
     
     #self.apertures = ApertureCollection( radii=np.zeros(4), 
                                          #coords=fakecoo, 
                                          #colours=['k','w','g','g'], 
                                          #ls=['dotted','dotted','solid','solid'])
     
     orange = colorConverter.to_rgba_array('orangered')         #HACK!
     
     psfaps = dict( coords=[coo,coo], 
                     radii=np.zeros(2), 
                     ls=':', 
                     colours=['k','w'],
                     pickradius=0, )
                     #**kw)
     photaps = dict( coords=coo, 
                     radii=[0],
                     gc='c',
                     badcolour=orange)     #FIXME:  keyword translation
     skyaps = dict( radii=np.zeros(2), 
                     coords=[coo,coo], )
                                 #**kw )
                                 
     self.apertures = StarApertures( psfaps, photaps, skyaps )
     
     self.has_plot = False
Beispiel #8
0
    def _shade_colors(self, color, normals):
        '''
        Shade *color* using normal vectors given by *normals*.
        *color* can also be an array of the same length as *normals*.
        '''

        shade = np.array([np.dot(n / proj3d.mod(n), [-1, -1, 0.5])
                          for n in normals])
        mask = ~np.isnan(shade)

        if len(shade[mask]) > 0:
            norm = Normalize(min(shade[mask]), max(shade[mask]))
            color = colorConverter.to_rgba_array(color)
            # shape of color should be (M, 4) (where M is number of faces)
            # shape of shade should be (M,)
            # colors should have final shape of (M, 4)
            alpha = color[:, 3]
            colors = (0.5 + norm(shade)[:, np.newaxis] * 0.5) * color
            colors[:, 3] = alpha
        else:
            colors = color.copy()

        return colors
Beispiel #9
0
def lighten(data,amt=0.10,is255=False):
    """Lighten a vector of colors by fraction `amt` of remaining possible intensity.
    
    New colors are calculated as::
     
        >>> new_colors = data + amt*(1.0-data)
        >>> new_colors[:,-1] = 1 # keep all alpha at 1.0
    
    Parameters
    ----------
    data : matplotlib colorspec or sequence of colorspecs
        input color(s)
    
    amt : float, optional
        Percentage by which to lighten `r`, `g`, and `b`. `a` remains unchanged
        (Default: 0.10)

    is255 : bool, optional
        If `True`, rgb values in `data` are assumed to be tween 0 and 255 
        rather than 0.0 and 1.0. In this case, return values will also 
        be between 0 and 255.
        
    Returns
    -------
    numpy.ndarray
        Lightened version of data
    """
    data = colorConverter.to_rgba_array(data)

    new_colors = data + amt*(1.0-data)
    if is255:
        new_colors = (255*new_colors).round()
    
    new_colors[:,-1] = data[:,-1]

    return new_colors
Beispiel #10
0
    def bar3d(self, x, y, z, dx, dy, dz, color='b',
              zsort='average', *args, **kwargs):
        '''
        Generate a 3D bar, or multiple bars.

        When generating multiple bars, x, y, z have to be arrays.
        dx, dy, dz can be arrays or scalars.

        *color* can be:

         - A single color value, to color all bars the same color.

         - An array of colors of length N bars, to color each bar
           independently.

         - An array of colors of length 6, to color the faces of the
           bars similarly.

         - An array of colors of length 6 * N bars, to color each face
           independently.

         When coloring the faces of the boxes specifically, this is
         the order of the coloring:

          1. -Z (bottom of box)
          2. +Z (top of box)
          3. -Y
          4. +Y
          5. -X
          6. +X

        Keyword arguments are passed onto
        :func:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`
        '''
        had_data = self.has_data()

        if not cbook.iterable(x):
            x = [x]
        if not cbook.iterable(y):
            y = [y]
        if not cbook.iterable(z):
            z = [z]

        if not cbook.iterable(dx):
            dx = [dx]
        if not cbook.iterable(dy):
            dy = [dy]
        if not cbook.iterable(dz):
            dz = [dz]

        if len(dx) == 1:
            dx = dx * len(x)
        if len(dy) == 1:
            dy = dy * len(y)
        if len(dz) == 1:
            dz = dz * len(z)

        if len(x) != len(y) or len(x) != len(z):
            warnings.warn('x, y, and z must be the same length.')

        minx, miny, minz = 1e20, 1e20, 1e20
        maxx, maxy, maxz = -1e20, -1e20, -1e20

        polys = []
        for xi, yi, zi, dxi, dyi, dzi in zip(x, y, z, dx, dy, dz):
            minx = min(xi, minx)
            maxx = max(xi + dxi, maxx)
            miny = min(yi, miny)
            maxy = max(yi + dyi, maxy)
            minz = min(zi, minz)
            maxz = max(zi + dzi, maxz)

            polys.extend([
                ((xi, yi, zi), (xi + dxi, yi, zi),
                    (xi + dxi, yi + dyi, zi), (xi, yi + dyi, zi)),
                ((xi, yi, zi + dzi), (xi + dxi, yi, zi + dzi),
                    (xi + dxi, yi + dyi, zi + dzi), (xi, yi + dyi, zi + dzi)),

                ((xi, yi, zi), (xi + dxi, yi, zi),
                    (xi + dxi, yi, zi + dzi), (xi, yi, zi + dzi)),
                ((xi, yi + dyi, zi), (xi + dxi, yi + dyi, zi),
                    (xi + dxi, yi + dyi, zi + dzi), (xi, yi + dyi, zi + dzi)),

                ((xi, yi, zi), (xi, yi + dyi, zi),
                    (xi, yi + dyi, zi + dzi), (xi, yi, zi + dzi)),
                ((xi + dxi, yi, zi), (xi + dxi, yi + dyi, zi),
                    (xi + dxi, yi + dyi, zi + dzi), (xi + dxi, yi, zi + dzi)),
            ])

        facecolors = []
        if color is None:
            # no color specified
            facecolors = [None] * len(x)
        elif len(color) == len(x):
            # bar colors specified, need to expand to number of faces
            for c in color:
                facecolors.extend([c] * 6)
        else:
            # a single color specified, or face colors specified explicitly
            facecolors = list(colorConverter.to_rgba_array(color))
            if len(facecolors) < len(x):
                facecolors *= (6 * len(x))

        normals = self._generate_normals(polys)
        sfacecolors = self._shade_colors(facecolors, normals)
        col = art3d.Poly3DCollection(polys,
                                     zsort=zsort,
                                     facecolor=sfacecolors,
                                     *args, **kwargs)
        self.add_collection(col)

        self.auto_scale_xyz((minx, maxx), (miny, maxy), (minz, maxz), had_data)
Beispiel #11
0
def draw_networkx_edges(G,
                        pos,
                        edgelist=None,
                        width=1.0,
                        edge_color='k',
                        style='solid',
                        alpha=None,
                        arrowstyle='-|>',
                        arrowsize=10,
                        edge_cmap=None,
                        edge_vmin=None,
                        edge_vmax=None,
                        ax=None,
                        arrows=True,
                        label=None,
                        node_size=300,
                        nodelist=None,
                        node_shape="o",
                        connectionstyle=None,
                        min_source_margin=0,
                        min_target_margin=0,
                        **kwds):
    """Draw the edges of the graph G.

    This draws only the edges of the graph G.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    edgelist : collection of edge tuples
       Draw only specified edges(default=G.edges())

    width : float, or array of floats
       Line width of edges (default=1.0)

    edge_color : color or array of colors (default='k')
       Edge color. Can be a single color or a sequence of colors with the same
       length as edgelist. Color can be string, or rgb (or rgba) tuple of
       floats from 0-1. If numeric values are specified they will be
       mapped to colors using the edge_cmap and edge_vmin,edge_vmax parameters.

    style : string
       Edge line style (default='solid') (solid|dashed|dotted,dashdot)

    alpha : float
       The edge transparency (default=None)

    edge_ cmap : Matplotlib colormap
       Colormap for mapping intensities of edges (default=None)

    edge_vmin,edge_vmax : floats
       Minimum and maximum for edge colormap scaling (default=None)

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    arrows : bool, optional (default=True)
       For directed graphs, if True draw arrowheads.
       Note: Arrows will be the same color as edges.

    arrowstyle : str, optional (default='-|>')
       For directed graphs, choose the style of the arrow heads.
       See :py:class: `matplotlib.patches.ArrowStyle` for more
       options.

    arrowsize : int, optional (default=10)
       For directed graphs, choose the size of the arrow head head's length and
       width. See :py:class: `matplotlib.patches.FancyArrowPatch` for attribute
       `mutation_scale` for more info.

    connectionstyle : str, optional (default=None)
       Pass the connectionstyle parameter to create curved arc of rounding
       radius rad. For example, connectionstyle='arc3,rad=0.2'.
       See :py:class: `matplotlib.patches.ConnectionStyle` and
       :py:class: `matplotlib.patches.FancyArrowPatch` for more info.

    label : [None| string]
       Label for legend

    min_source_margin : int, optional (default=0)
       The minimum margin (gap) at the begining of the edge at the source.

    min_target_margin : int, optional (default=0)
       The minimum margin (gap) at the end of the edge at the target.

    Returns
    -------
    matplotlib.collection.LineCollection
        `LineCollection` of the edges

    list of matplotlib.patches.FancyArrowPatch
        `FancyArrowPatch` instances of the directed edges

    Depending whether the drawing includes arrows or not.

    Notes
    -----
    For directed graphs, arrows are drawn at the head end.  Arrows can be
    turned off with keyword arrows=False. Be sure to include `node_size` as a
    keyword argument; arrows are drawn considering the size of nodes.

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))

    >>> G = nx.DiGraph()
    >>> G.add_edges_from([(1, 2), (1, 3), (2, 3)])
    >>> arcs = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))
    >>> alphas = [0.3, 0.4, 0.5]
    >>> for i, arc in enumerate(arcs):  # change alpha values of arcs
    ...     arc.set_alpha(alphas[i])

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_labels()
    draw_networkx_edge_labels()
    """
    try:
        import matplotlib
        import matplotlib.pyplot as plt
        from matplotlib.colors import colorConverter, Colormap, Normalize
        from matplotlib.collections import LineCollection
        from matplotlib.patches import FancyArrowPatch
        import numpy as np
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()

    if edgelist is None:
        edgelist = list(G.edges())

    if not edgelist or len(edgelist) == 0:  # no edges!
        return None

    if nodelist is None:
        nodelist = list(G.nodes())

    # FancyArrowPatch handles color=None different from LineCollection
    if edge_color is None:
        edge_color = 'k'

    # set edge positions
    edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])

    # Check if edge_color is an array of floats and map to edge_cmap.
    # This is the only case handled differently from matplotlib
    if np.iterable(edge_color) and (len(edge_color) == len(edge_pos)) \
            and np.alltrue([isinstance(c, Number) for c in edge_color]):
        if edge_cmap is not None:
            assert (isinstance(edge_cmap, Colormap))
        else:
            edge_cmap = plt.get_cmap()
        if edge_vmin is None:
            edge_vmin = min(edge_color)
        if edge_vmax is None:
            edge_vmax = max(edge_color)
        color_normal = Normalize(vmin=edge_vmin, vmax=edge_vmax)
        edge_color = [edge_cmap(color_normal(e)) for e in edge_color]

    if (not G.is_directed() or not arrows):
        edge_collection = LineCollection(edge_pos,
                                         colors=edge_color,
                                         linewidths=width,
                                         antialiaseds=(1, ),
                                         linestyle=style,
                                         transOffset=ax.transData,
                                         alpha=alpha)

        edge_collection.set_zorder(1)  # edges go behind nodes
        edge_collection.set_label(label)
        ax.add_collection(edge_collection)

        return edge_collection

    arrow_collection = None

    if G.is_directed() and arrows:
        # Note: Waiting for someone to implement arrow to intersection with
        # marker.  Meanwhile, this works well for polygons with more than 4
        # sides and circle.

        def to_marker_edge(marker_size, marker):
            if marker in "s^>v<d":  # `large` markers need extra space
                return np.sqrt(2 * marker_size) / 2
            else:
                return np.sqrt(marker_size) / 2

        # Draw arrows with `matplotlib.patches.FancyarrowPatch`
        arrow_collection = []
        mutation_scale = arrowsize  # scale factor of arrow head

        # FancyArrowPatch doesn't handle color strings
        arrow_colors = colorConverter.to_rgba_array(edge_color, alpha)
        for i, (src, dst) in enumerate(edge_pos):
            x1, y1 = src
            x2, y2 = dst
            shrink_source = 0  # space from source to tail
            shrink_target = 0  # space from  head to target
            if np.iterable(node_size):  # many node sizes
                src_node, dst_node = edgelist[i][:2]
                index_node = nodelist.index(dst_node)
                marker_size = node_size[index_node]
                shrink_target = to_marker_edge(marker_size, node_shape)
            else:
                shrink_target = to_marker_edge(node_size, node_shape)

            if shrink_source < min_source_margin:
                shrink_source = min_source_margin

            if shrink_target < min_target_margin:
                shrink_target = min_target_margin

            if len(arrow_colors) == len(edge_pos):
                arrow_color = arrow_colors[i]
            elif len(arrow_colors) == 1:
                arrow_color = arrow_colors[0]
            else:  # Cycle through colors
                arrow_color = arrow_colors[i % len(arrow_colors)]

            if np.iterable(width):
                if len(width) == len(edge_pos):
                    line_width = width[i]
                else:
                    line_width = width[i % len(width)]
            else:
                line_width = width

            arrow = FancyArrowPatch((x1, y1), (x2, y2),
                                    arrowstyle=arrowstyle,
                                    shrinkA=shrink_source,
                                    shrinkB=shrink_target,
                                    mutation_scale=mutation_scale,
                                    color=arrow_color,
                                    linewidth=line_width,
                                    connectionstyle=connectionstyle,
                                    zorder=1)  # arrows go behind nodes

            # There seems to be a bug in matplotlib to make collections of
            # FancyArrowPatch instances. Until fixed, the patches are added
            # individually to the axes instance.
            arrow_collection.append(arrow)
            ax.add_patch(arrow)

    # update view
    minx = np.amin(np.ravel(edge_pos[:, :, 0]))
    maxx = np.amax(np.ravel(edge_pos[:, :, 0]))
    miny = np.amin(np.ravel(edge_pos[:, :, 1]))
    maxy = np.amax(np.ravel(edge_pos[:, :, 1]))

    w = maxx - minx
    h = maxy - miny
    padx, pady = 0.05 * w, 0.05 * h
    corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady)
    ax.update_datalim(corners)
    ax.autoscale_view()

    ax.tick_params(axis='both',
                   which='both',
                   bottom=False,
                   left=False,
                   labelbottom=False,
                   labelleft=False)

    return arrow_collection
Beispiel #12
0
def draw_networkx_edges(
    G,
    pos,
    edgelist=None,
    width=1.0,
    edge_color="k",
    style="solid",
    alpha=None,
    arrowstyle="-|>",
    arrowsize=3,
    edge_cmap=None,
    edge_vmin=None,
    edge_vmax=None,
    ax=None,
    arrows=True,
    label=None,
    node_size=300,
    nodelist=None,
    node_shape="o",
    connectionstyle=None,
    min_source_margin=0,
    min_target_margin=0,
):
    """Draw the edges of the graph G. Adjusted from networkx."""
    try:
        import matplotlib.pyplot as plt
        from matplotlib.colors import colorConverter, Colormap, Normalize
        from matplotlib.collections import LineCollection
        from matplotlib.patches import FancyArrowPatch
        from numbers import Number
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()

    if edgelist is None:
        edgelist = list(G.edges())

    if not edgelist or len(edgelist) == 0:  # no edges!
        return None

    if nodelist is None:
        nodelist = list(G.nodes())

    # FancyArrowPatch handles color=None different from LineCollection
    if edge_color is None:
        edge_color = "k"

    # set edge positions
    edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])

    # Check if edge_color is an array of floats and map to edge_cmap.
    # This is the only case handled differently from matplotlib
    if (
        np.iterable(edge_color)
        and (len(edge_color) == len(edge_pos))
        and np.alltrue([isinstance(c, Number) for c in edge_color])
    ):
        if edge_cmap is not None:
            assert isinstance(edge_cmap, Colormap)
        else:
            edge_cmap = plt.get_cmap()
        if edge_vmin is None:
            edge_vmin = min(edge_color)
        if edge_vmax is None:
            edge_vmax = max(edge_color)
        color_normal = Normalize(vmin=edge_vmin, vmax=edge_vmax)
        edge_color = [edge_cmap(color_normal(e)) for e in edge_color]

    if not G.is_directed() or not arrows:
        edge_collection = LineCollection(
            edge_pos,
            colors=edge_color,
            linewidths=width,
            antialiaseds=(1,),
            linestyle=style,
            transOffset=ax.transData,
            alpha=alpha,
        )

        edge_collection.set_cmap(edge_cmap)
        edge_collection.set_clim(edge_vmin, edge_vmax)

        edge_collection.set_zorder(1)  # edges go behind nodes
        edge_collection.set_label(label)
        ax.add_collection(edge_collection)

        return edge_collection

    arrow_collection = None

    if G.is_directed() and arrows:
        # Note: Waiting for someone to implement arrow to intersection with
        # marker.  Meanwhile, this works well for polygons with more than 4
        # sides and circle.

        def to_marker_edge(marker_size, marker):
            if marker in "s^>v<d":  # `large` markers need extra space
                return np.sqrt(2 * marker_size) / 2
            else:
                return np.sqrt(marker_size) / 2

        # Draw arrows with `matplotlib.patches.FancyarrowPatch`
        arrow_collection = []
        mutation_scale = arrowsize  # scale factor of arrow head

        # FancyArrowPatch doesn't handle color strings
        arrow_colors = colorConverter.to_rgba_array(edge_color, alpha)
        for i, (src, dst) in enumerate(edge_pos):
            x1, y1 = src
            x2, y2 = dst
            shrink_source = 0  # space from source to tail
            shrink_target = 0  # space from  head to target
            if np.iterable(node_size):  # many node sizes
                source, target = edgelist[i][:2]
                source_node_size = node_size[nodelist.index(source)]
                target_node_size = node_size[nodelist.index(target)]
                shrink_source = to_marker_edge(source_node_size, node_shape)
                shrink_target = to_marker_edge(target_node_size, node_shape)
            else:
                shrink_source = shrink_target = to_marker_edge(node_size, node_shape)

            if shrink_source < min_source_margin:
                shrink_source = min_source_margin

            if shrink_target < min_target_margin:
                shrink_target = min_target_margin

            if len(arrow_colors) == len(edge_pos):
                arrow_color = arrow_colors[i]
            elif len(arrow_colors) == 1:
                arrow_color = arrow_colors[0]
            else:  # Cycle through colors
                arrow_color = arrow_colors[i % len(arrow_colors)]

            if np.iterable(width):
                if len(width) == len(edge_pos):
                    line_width = width[i]
                else:
                    line_width = width[i % len(width)]
            else:
                line_width = width

            arrow = FancyArrowPatch(
                (x1, y1),
                (x2, y2),
                arrowstyle=arrowstyle,
                shrinkA=shrink_source,
                shrinkB=shrink_target,
                mutation_scale=mutation_scale,
                color=arrow_color,
                linewidth=line_width,
                connectionstyle=connectionstyle,
                linestyle=style,
                zorder=1,
            )  # arrows go behind nodes

            # There seems to be a bug in matplotlib to make collections of
            # FancyArrowPatch instances. Until fixed, the patches are added
            # individually to the axes instance.
            arrow_collection.append(arrow)
            ax.add_patch(arrow)

    # update view
    minx = np.amin(np.ravel(edge_pos[:, :, 0]))
    maxx = np.amax(np.ravel(edge_pos[:, :, 0]))
    miny = np.amin(np.ravel(edge_pos[:, :, 1]))
    maxy = np.amax(np.ravel(edge_pos[:, :, 1]))

    w = maxx - minx
    h = maxy - miny
    padx, pady = 0.05 * w, 0.05 * h
    corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady)
    ax.update_datalim(corners)
    ax.autoscale_view()

    ax.tick_params(
        axis="both",
        which="both",
        bottom=False,
        left=False,
        labelbottom=False,
        labelleft=False,
    )

    return arrow_collection
Beispiel #13
0
def draw_networkx_edges(
    G,
    pos,
    edgelist=None,
    width=1.0,
    edge_color="k",
    style="solid",
    alpha=None,
    arrowstyle=None,
    arrowsize=10,
    edge_cmap=None,
    edge_vmin=None,
    edge_vmax=None,
    ax=None,
    arrows=None,
    label=None,
    node_size=300,
    nodelist=None,
    node_shape="o",
    connectionstyle="arc3",
    min_source_margin=0,
    min_target_margin=0,
):
    """Draw the edges of the graph G.

    This draws only the edges of the graph G.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    edgelist : collection of edge tuples
       Draw only specified edges(default=G.edges())

    width : float, or array of floats
       Line width of edges (default=1.0)

    edge_color : color or array of colors (default='k')
       Edge color. Can be a single color or a sequence of colors with the same
       length as edgelist. Color can be string, or rgb (or rgba) tuple of
       floats from 0-1. If numeric values are specified they will be
       mapped to colors using the edge_cmap and edge_vmin,edge_vmax parameters.

    style : string
       Edge line style (default='solid') (solid|dashed|dotted,dashdot)

    alpha : float
       The edge transparency (default=None)

    edge_ cmap : Matplotlib colormap
       Colormap for mapping intensities of edges (default=None)

    edge_vmin,edge_vmax : floats
       Minimum and maximum for edge colormap scaling (default=None)

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    arrows : bool, optional (default=True)
       For directed graphs, if True draw arrowheads by default.  Ignored
       if *arrowstyle* is passed.

       Note: Arrows will be the same color as edges.

    arrowstyle : str, optional (default=None)
       For directed graphs and *arrows==True* defaults to ``'-|>'`` otherwise
       defaults to ``'-'``.

       See `matplotlib.patches.ArrowStyle` for more options.

    arrowsize : int, optional (default=10)
       For directed graphs, choose the size of the arrow head head's length and
       width. See `matplotlib.patches.FancyArrowPatch` for attribute
       `mutation_scale` for more info.

    connectionstyle : str, optional (default="arc3")
       Pass the connectionstyle parameter to create curved arc of rounding
       radius rad. For example, connectionstyle='arc3,rad=0.2'.
       See `matplotlib.patches.ConnectionStyle` and
       `matplotlib.patches.FancyArrowPatch` for more info.

    label : [None| string]
       Label for legend

    min_source_margin : int, optional (default=0)
       The minimum margin (gap) at the begining of the edge at the source.

    min_target_margin : int, optional (default=0)
       The minimum margin (gap) at the end of the edge at the target.

    Returns
    -------
    list of matplotlib.patches.FancyArrowPatch
        `FancyArrowPatch` instances of the directed edges

    Notes
    -----
    For directed graphs, arrows are drawn at the head end.  Arrows can be
    turned off with keyword arrows=False or by passing an arrowstyle without
    an arrow on the end.

    Be sure to include `node_size` as a keyword argument; arrows are
    drawn considering the size of nodes.

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))

    >>> G = nx.DiGraph()
    >>> G.add_edges_from([(1, 2), (1, 3), (2, 3)])
    >>> arcs = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))
    >>> alphas = [0.3, 0.4, 0.5]
    >>> for i, arc in enumerate(arcs):  # change alpha values of arcs
    ...     arc.set_alpha(alphas[i])

    Also see the NetworkX drawing examples at
    https://networkx.org/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_labels()
    draw_networkx_edge_labels()

    """
    import matplotlib.pyplot as plt
    from matplotlib.colors import colorConverter, Colormap, Normalize
    from matplotlib.patches import FancyArrowPatch, ConnectionStyle
    from matplotlib.path import Path
    import numpy as np

    if arrowstyle is not None and arrows is not None:
        warnings.warn(f"You passed both arrowstyle={arrowstyle} and "
                      f"arrows={arrows}.  Because you set a non-default "
                      "*arrowstyle*, arrows will be ignored.")

    if arrowstyle is None:
        if G.is_directed() and arrows:
            arrowstyle = "-|>"
        else:
            arrowstyle = "-"

    if ax is None:
        ax = plt.gca()

    if edgelist is None:
        edgelist = list(G.edges())

    if len(edgelist) == 0:  # no edges!
        return []

    if nodelist is None:
        nodelist = list(G.nodes())

    # FancyArrowPatch handles color=None different from LineCollection
    if edge_color is None:
        edge_color = "k"

    # set edge positions
    edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])

    # Check if edge_color is an array of floats and map to edge_cmap.
    # This is the only case handled differently from matplotlib
    if (np.iterable(edge_color) and (len(edge_color) == len(edge_pos))
            and np.alltrue([isinstance(c, Number) for c in edge_color])):
        if edge_cmap is not None:
            assert isinstance(edge_cmap, Colormap)
        else:
            edge_cmap = plt.get_cmap()
        if edge_vmin is None:
            edge_vmin = min(edge_color)
        if edge_vmax is None:
            edge_vmax = max(edge_color)
        color_normal = Normalize(vmin=edge_vmin, vmax=edge_vmax)
        edge_color = [edge_cmap(color_normal(e)) for e in edge_color]

    # Note: Waiting for someone to implement arrow to intersection with
    # marker.  Meanwhile, this works well for polygons with more than 4
    # sides and circle.

    def to_marker_edge(marker_size, marker):
        if marker in "s^>v<d":  # `large` markers need extra space
            return np.sqrt(2 * marker_size) / 2
        else:
            return np.sqrt(marker_size) / 2

    # Draw arrows with `matplotlib.patches.FancyarrowPatch`
    arrow_collection = []
    mutation_scale = arrowsize  # scale factor of arrow head

    # compute view
    minx = np.amin(np.ravel(edge_pos[:, :, 0]))
    maxx = np.amax(np.ravel(edge_pos[:, :, 0]))
    miny = np.amin(np.ravel(edge_pos[:, :, 1]))
    maxy = np.amax(np.ravel(edge_pos[:, :, 1]))
    w = maxx - minx
    h = maxy - miny

    base_connection_style = ConnectionStyle(connectionstyle)

    def _connectionstyle(posA, posB, *args, **kwargs):
        # check if we need to do a self-loop
        if np.all(posA == posB):
            # this is called with _screen space_ values so covert back
            # to data space
            data_loc = ax.transData.inverted().transform(posA)
            v_shift = 0.1 * h
            h_shift = v_shift * 0.5
            # put the top of the loop first so arrow is not hidden by node
            path = [
                # 1
                data_loc + np.asarray([0, v_shift]),
                # 4 4 4
                data_loc + np.asarray([h_shift, v_shift]),
                data_loc + np.asarray([h_shift, 0]),
                data_loc,
                # 4 4 4
                data_loc + np.asarray([-h_shift, 0]),
                data_loc + np.asarray([-h_shift, v_shift]),
                data_loc + np.asarray([0, v_shift]),
            ]

            ret = Path(ax.transData.transform(path), [1, 4, 4, 4, 4, 4, 4])
        # if not, fall back to the user specified behavior
        else:
            ret = base_connection_style(posA, posB, *args, **kwargs)

        return ret

    # FancyArrowPatch doesn't handle color strings
    arrow_colors = colorConverter.to_rgba_array(edge_color, alpha)
    for i, (src, dst) in enumerate(edge_pos):
        x1, y1 = src
        x2, y2 = dst
        shrink_source = 0  # space from source to tail
        shrink_target = 0  # space from  head to target
        if np.iterable(node_size):  # many node sizes
            source, target = edgelist[i][:2]
            source_node_size = node_size[nodelist.index(source)]
            target_node_size = node_size[nodelist.index(target)]
            shrink_source = to_marker_edge(source_node_size, node_shape)
            shrink_target = to_marker_edge(target_node_size, node_shape)
        else:
            shrink_source = shrink_target = to_marker_edge(
                node_size, node_shape)

        if shrink_source < min_source_margin:
            shrink_source = min_source_margin

        if shrink_target < min_target_margin:
            shrink_target = min_target_margin

        if len(arrow_colors) == len(edge_pos):
            arrow_color = arrow_colors[i]
        elif len(arrow_colors) == 1:
            arrow_color = arrow_colors[0]
        else:  # Cycle through colors
            arrow_color = arrow_colors[i % len(arrow_colors)]

        if np.iterable(width):
            if len(width) == len(edge_pos):
                line_width = width[i]
            else:
                line_width = width[i % len(width)]
        else:
            line_width = width

        arrow = FancyArrowPatch(
            (x1, y1),
            (x2, y2),
            arrowstyle=arrowstyle,
            shrinkA=shrink_source,
            shrinkB=shrink_target,
            mutation_scale=mutation_scale,
            color=arrow_color,
            linewidth=line_width,
            connectionstyle=_connectionstyle,
            linestyle=style,
            zorder=1,
        )  # arrows go behind nodes

        arrow_collection.append(arrow)
        ax.add_patch(arrow)

    # update view
    padx, pady = 0.05 * w, 0.05 * h
    corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady)
    ax.update_datalim(corners)
    ax.autoscale_view()

    ax.tick_params(
        axis="both",
        which="both",
        bottom=False,
        left=False,
        labelbottom=False,
        labelleft=False,
    )

    return arrow_collection
Beispiel #14
0
def w2b(artist):        #TODO:  this can be a decorator!
    ca = artist.get_colors()
    w = np.all(ca == colorConverter.to_rgba_array('w'), 1 )
    ca[w] = colorConverter.to_rgba_array('k')
    artist.set_color( ca )
Beispiel #15
0
def set_colormap(h, colorList, vabs=None):
    """
    Apply a customized color map using a simple list of colors
    
    :Call:
        >>> set_colormap(h, colorList)
    
    :Parameters:
        *h*: Any matplotlib object with a *set_cmap* method
            Plot handle to have its colormap altered
        *colorList*: list of color descriptors
            List of colors or list of colors and break points
    
    :Returns:
        ``None``
        
    :Examples:
        The usual method is to apply a list of colors to an object with a
        colormap, for example a contour plot.  We begin by drawing a sample
        contour plot.
        
            >>> import numpy as np
            >>> import matplotlib.pyplot as plt
            >>> x = np.linspace(-3, 3, 61)
            >>> y = np.linspace(-2, 2, 41)
            >>> X, Y = np.meshgrid(x, y)
            >>> Z = np.sin(2*X) + np.cos(2*X) + 1.5*np.exp(-X*X-Y*Y)
            >>> h = plt.contourf(X, Y, Z)
        
        The first example changes the colormap to a monochrome scale with darker
        blues meaning low and lighter colors for high values.
        
            >>> pyxflow.set_colormap(h, ['Navy', 'b', (1,1,1)])
        
        Monochrome color themes are ideal for situations where the values are
        all positive.  In this case, some regions of the plot are negative, so
        it is helpful to use the colormap to highlight regions that are zero.
        
            >>> pyxflow.set_colormap(h, ['Navy', 'w', 'Maroon'])
            
        However, this plot turns out to have a maximum of about ``+3.0`` while
        the minimum is about ``-2.0``.  Therefore evenly spacing out these
        colors really highlights where the plot crosses the midpoint of this
        range, ``+0.5``.  We can fix this by specifying the _values_ we want the
        colors to occur at.
        
            >>> pyxflow.set_colormap(h, [(-2,'Navy'), (0,'w'), (3,'DarkRed')])
        
        This can also be done using relative values if you can determine them
        manually.  Thus the following gives nearly the same results.
        
            >>> pyxflow.set_colormap(h, [(0,'Navy'), (0.4,'w'), (1,'Maroon')])
        
        The function guesses which type of values you intended to use.  The only
        time this causes trouble is when you want to highlight absolute values
        between ``0`` and ``1``, but the limits of the contour plot go outside. 
        For this situation, use the following syntax.
        
            >>> pyxflow.set_colormap(h, [(0,'c'), (1,'Orange')], vabs=True)
            
        By repeating the same value twice in the color list, it is possible to
        dramatically highlight where the plot crosses a certain value.  This
        may be useful, for example, in the case of separating subsonic and
        supersonic flow.
        
            >>> h = plt.contourf(X, Y, Z, levels=np.linspace(-2,3,26)
            >>> pyxflow.set_colormap(h, [(-2,'r'),(0,'m'),(0,'c'),(2,'Navy')])
            
        Because Matplotlib's color converter is used, there are many ways to
        specify a color.  The following includes a red-green-blue tuple, a
        partially transparent color, and an HTML hash.
        
            >>> pyxflow.set_colormap(h, [(0.8,0.4,0.2), (0,0,1,0.5), '#0a8332'])
            
    """
    # Versions:
    #  2013-12-15 @dalle   : Introductory version

    # Determine the nature of the handle.
    if not hasattr(h, 'set_cmap'):
        raise AttributeError(
            "Input to `set_colormap` must have 'set_cmap' attribute.")

    # Check for named colormap
    if isinstance(colorList, str):
        # Pass it to set_cmap and see what happens.
        try:
            h.set_cmap(colorList)
            return None
        except:
            NotImplementedError(
                "Additional named colormaps have not been implemented.")

    # Get dimensions of the list.
    nColors = len(colorList)
    
    # Determine if break points are specified.
    if np.isscalar(colorList[0]) or len(colorList[0])!=2:
        # Default break points
        vList = np.linspace(0, 1, nColors)
        # Names of the colors
        cList = list(colorList)
    else:
        # User-specified break points
        vList = np.array([np.float(c[0]) for c in colorList])
        # Names of the colors
        cList = [c[1] for c in colorList]
        
    # Process the default scaling method if necessary.
    if vabs is None:
        if min(vList) == 0 and max(vList) == 1:
            # Scale the values from 0 to 1
            vabs = False
        else:
            # Use vList as absolute values.
            vabs = True
            
    # Scale the colors if requested.
    if vabs:
        # Set the color limits.
        h.set_clim(vList[0], vList[-1])
        # Re-scale the list to go from 0 to 1
        vList = (vList - vList[0]) / (vList[-1] - vList[0])
    
    # Convert the colors to RGB.
    rgba1List = colorConverter.to_rgba_array(cList)
    rgba2List = colorConverter.to_rgba_array(cList)
    # Find repeated colors.
    iRepeat = np.nonzero(np.diff(vList) <= 1e-8)
    # Compress the list of breakpoints.
    vList = np.delete(vList, iRepeat)
    # Process the repeated colors in reverse order.
    for i in iRepeat[::-1]:
        # Delete the second color at the same point from the "left" list.
        rgba1List = np.delete(rgba1List, i, 0)
        # Delete the first color at the same point from the "right" list.
        rgba2List = np.delete(rgba2List, i + 1, 0)
    
    # Make the lists for the individual components (red, green, blue).
    rList = [(vList[i], rgba2List[i, 0], rgba1List[i, 0])
        for i in range(vList.size)]
    gList = [(vList[i], rgba2List[i, 1], rgba1List[i, 1])
        for i in range(vList.size)]
    bList = [(vList[i], rgba2List[i, 2], rgba1List[i, 2])
        for i in range(vList.size)]
    aList = [(vList[i], rgba2List[i, 3], rgba1List[i, 3])
        for i in range(vList.size)]
    # Make the required dictionary for the colormap.
    cdict = {'red': rList, 'green': gList, 'blue': bList, 'alpha': aList}
    # Set the colormap.
    cm = LinearSegmentedColormap('custom', cdict)
    # Apply the colormap
    h.set_cmap(cm)
    # Update
    if plt.isinteractive():
        plt.draw()
Beispiel #16
0
    def _debug_plot(self):
        assert self._debug, "must enable _debug, to debug-plot"
        import pylab
#         from mpl_toolkits.mplot3d import Axes3D
        figs = [pylab.figure('BGPLVM DEBUG', figsize=(12, 4))]
#         fig.clf()

        # log like
#         splotshape = (6, 4)
#         ax1 = pylab.subplot2grid(splotshape, (0, 0), 1, 4)
        ax1 = self._debug_get_axis(figs)
        ax1.text(.5, .5, "Optimization", alpha=.3, transform=ax1.transAxes,
                 ha='center', va='center')
        kllls = np.array(self._savedklll)
        LL, = ax1.plot(kllls[:, 0], kllls[:, 1] - kllls[:, 2], '-', label=r'$\log p(\mathbf{Y})$', mew=1.5)
        KL, = ax1.plot(kllls[:, 0], kllls[:, 2], '-', label=r'$\mathcal{KL}(p||q)$', mew=1.5)
        L, = ax1.plot(kllls[:, 0], kllls[:, 1], '-', label=r'$L$', mew=1.5) # \mathds{E}_{q(\mathbf{X})}[p(\mathbf{Y|X})\frac{p(\mathbf{X})}{q(\mathbf{X})}]

        param_dict = dict(self._savedparams)
        gradient_dict = dict(self._savedgradients)
#         kmm_dict = dict(self._savedpsiKmm)
        iters = np.array(param_dict.keys())
        ABCD_dict = np.array(self._savedABCD)
        self.showing = 0

#         ax2 = pylab.subplot2grid(splotshape, (1, 0), 2, 4)
        figs.append(pylab.figure("BGPLVM DEBUG X", figsize=(12, 4)))
        ax2 = self._debug_get_axis(figs)
        ax2.text(.5, .5, r"$\mathbf{X}$", alpha=.5, transform=ax2.transAxes,
                 ha='center', va='center')
        figs[-1].canvas.draw()
        figs[-1].tight_layout(rect=(0, 0, 1, .86))
#         ax3 = pylab.subplot2grid(splotshape, (3, 0), 2, 4, sharex=ax2)
        figs.append(pylab.figure("BGPLVM DEBUG S", figsize=(12, 4)))
        ax3 = self._debug_get_axis(figs)
        ax3.text(.5, .5, r"$\mathbf{S}$", alpha=.5, transform=ax3.transAxes,
                 ha='center', va='center')
        figs[-1].canvas.draw()
        figs[-1].tight_layout(rect=(0, 0, 1, .86))
#         ax4 = pylab.subplot2grid(splotshape, (5, 0), 2, 2)
        figs.append(pylab.figure("BGPLVM DEBUG Z", figsize=(6, 4)))
        ax4 = self._debug_get_axis(figs)
        ax4.text(.5, .5, r"$\mathbf{Z}$", alpha=.5, transform=ax4.transAxes,
                 ha='center', va='center')
        figs[-1].canvas.draw()
        figs[-1].tight_layout(rect=(0, 0, 1, .86))
#         ax5 = pylab.subplot2grid(splotshape, (5, 2), 2, 2)
        figs.append(pylab.figure("BGPLVM DEBUG theta", figsize=(6, 4)))
        ax5 = self._debug_get_axis(figs)
        ax5.text(.5, .5, r"${\theta}$", alpha=.5, transform=ax5.transAxes,
                 ha='center', va='center')
        figs[-1].canvas.draw()
        figs[-1].tight_layout(rect=(.15, 0, 1, .86))
#         figs.append(pylab.figure("BGPLVM DEBUG Kmm", figsize=(12, 6)))
#         fig = figs[-1]
#         ax6 = fig.add_subplot(121)
#         ax6.text(.5, .5, r"${\mathbf{K}_{mm}}$", color='magenta', alpha=.5, transform=ax6.transAxes,
#                  ha='center', va='center')
#         ax7 = fig.add_subplot(122)
#         ax7.text(.5, .5, r"${\frac{dL}{dK_{mm}}}$", color='magenta', alpha=.5, transform=ax7.transAxes,
#                  ha='center', va='center')
        figs.append(pylab.figure("BGPLVM DEBUG Kmm", figsize=(12, 6)))
        fig = figs[-1]
        ax8 = fig.add_subplot(121)
        ax8.text(.5, .5, r"${\mathbf{A,B,C,input_dim}}$", color='k', alpha=.5, transform=ax8.transAxes,
                 ha='center', va='center')
        ax8.plot(ABCD_dict[:, 0], ABCD_dict[:, 1], label='A')
        ax8.plot(ABCD_dict[:, 0], ABCD_dict[:, 2], label='B')
        ax8.plot(ABCD_dict[:, 0], ABCD_dict[:, 3], label='C')
        ax8.plot(ABCD_dict[:, 0], ABCD_dict[:, 4], label='input_dim')
        ax8.legend()
        figs[-1].canvas.draw()
        figs[-1].tight_layout(rect=(.15, 0, 1, .86))

        X, S, Z, theta = self._debug_filter_params(param_dict[self.showing])
        Xg, Sg, Zg, thetag = self._debug_filter_params(gradient_dict[self.showing])
#         Xg, Sg, Zg, thetag = -Xg, -Sg, -Zg, -thetag

        quiver_units = 'xy'
        quiver_scale = 1
        quiver_scale_units = 'xy'
        Xlatentplts = ax2.plot(X, ls="-", marker="x")
        colors = colorConverter.to_rgba_array([p.get_color() for p in Xlatentplts], .4)
        Ulatent = np.zeros_like(X)
        xlatent = np.tile(np.arange(0, X.shape[0])[:, None], X.shape[1])
        Xlatentgrads = ax2.quiver(xlatent, X, Ulatent, Xg, color=colors,
                                  units=quiver_units, scale_units=quiver_scale_units,
                                  scale=quiver_scale)

        Slatentplts = ax3.plot(S, ls="-", marker="x")
        Slatentgrads = ax3.quiver(xlatent, S, Ulatent, Sg, color=colors,
                                  units=quiver_units, scale_units=quiver_scale_units,
                                  scale=quiver_scale)
        ax3.set_ylim(0, 1.)

        xZ = np.tile(np.arange(0, Z.shape[0])[:, None], Z.shape[1])
        UZ = np.zeros_like(Z)
        Zplts = ax4.plot(Z, ls="-", marker="x")
        Zgrads = ax4.quiver(xZ, Z, UZ, Zg, color=colors,
                                  units=quiver_units, scale_units=quiver_scale_units,
                                  scale=quiver_scale)

        xtheta = np.arange(len(theta))
        Utheta = np.zeros_like(theta)
        thetaplts = ax5.bar(xtheta - .4, theta, color=colors)
        thetagrads = ax5.quiver(xtheta, theta, Utheta, thetag, color=colors,
                                  units=quiver_units, scale_units=quiver_scale_units,
                                  scale=quiver_scale,
                                  edgecolors=('k',), linewidths=[1])
        pylab.setp(thetaplts, zorder=0)
        pylab.setp(thetagrads, zorder=10)
        ax5.set_xticks(np.arange(len(theta)))
        ax5.set_xticklabels(self._get_param_names()[-len(theta):], rotation=17)

#         imkmm = ax6.imshow(kmm_dict[self.showing][0])
#         from mpl_toolkits.axes_grid1 import make_axes_locatable
#         divider = make_axes_locatable(ax6)
#         caxkmm = divider.append_axes("right", "5%", pad="1%")
#         cbarkmm = pylab.colorbar(imkmm, cax=caxkmm)
#
#         imkmmdl = ax7.imshow(kmm_dict[self.showing][1])
#         divider = make_axes_locatable(ax7)
#         caxkmmdl = divider.append_axes("right", "5%", pad="1%")
#         cbarkmmdl = pylab.colorbar(imkmmdl, cax=caxkmmdl)

#         input_dimleg = ax1.legend(Xlatentplts, [r"$input_dim_{}$".format(i + 1) for i in range(self.input_dim)],
#                    loc=3, ncol=self.input_dim, bbox_to_anchor=(0, 1.15, 1, 1.15),
#                    borderaxespad=0, mode="expand")
        ax2.legend(Xlatentplts, [r"$input_dim_{}$".format(i + 1) for i in range(self.input_dim)],
                   loc=3, ncol=self.input_dim, bbox_to_anchor=(0, 1.1, 1, 1.1),
                   borderaxespad=0, mode="expand")
        ax3.legend(Xlatentplts, [r"$input_dim_{}$".format(i + 1) for i in range(self.input_dim)],
                   loc=3, ncol=self.input_dim, bbox_to_anchor=(0, 1.1, 1, 1.1),
                   borderaxespad=0, mode="expand")
        ax4.legend(Xlatentplts, [r"$input_dim_{}$".format(i + 1) for i in range(self.input_dim)],
                   loc=3, ncol=self.input_dim, bbox_to_anchor=(0, 1.1, 1, 1.1),
                   borderaxespad=0, mode="expand")
        ax5.legend(Xlatentplts, [r"$input_dim_{}$".format(i + 1) for i in range(self.input_dim)],
                   loc=3, ncol=self.input_dim, bbox_to_anchor=(0, 1.1, 1, 1.1),
                   borderaxespad=0, mode="expand")
        Lleg = ax1.legend()
        Lleg.draggable()
#         ax1.add_artist(input_dimleg)

        indicatorKL, = ax1.plot(kllls[self.showing, 0], kllls[self.showing, 2], 'o', c=KL.get_color())
        indicatorLL, = ax1.plot(kllls[self.showing, 0], kllls[self.showing, 1] - kllls[self.showing, 2], 'o', c=LL.get_color())
        indicatorL, = ax1.plot(kllls[self.showing, 0], kllls[self.showing, 1], 'o', c=L.get_color())
#         for err in self._savederrors:
#             if err < kllls.shape[0]:
#                 ax1.scatter(kllls[err, 0], kllls[err, 2], s=50, marker=(5, 2), c=KL.get_color())
#                 ax1.scatter(kllls[err, 0], kllls[err, 1] - kllls[err, 2], s=50, marker=(5, 2), c=LL.get_color())
#                 ax1.scatter(kllls[err, 0], kllls[err, 1], s=50, marker=(5, 2), c=L.get_color())

#         try:
#             for f in figs:
#                 f.canvas.draw()
#                 f.tight_layout(box=(0, .15, 1, .9))
# #             pylab.draw()
# #             pylab.tight_layout(box=(0, .1, 1, .9))
#         except:
#             pass

        # parameter changes
        # ax2 = pylab.subplot2grid((4, 1), (1, 0), 3, 1, projection='3d')
        button_options = [0, 0] # [0]: clicked -- [1]: dragged

        def update_plots(event):
            if button_options[0] and not button_options[1]:
#               event.button, event.x, event.y, event.xdata, event.ydata)
                tmp = np.abs(iters - event.xdata)
                closest_hit = iters[tmp == tmp.min()][0]

                if closest_hit != self.showing:
                    self.showing = closest_hit
                    # print closest_hit, iters, event.xdata

                    indicatorLL.set_data(self.showing, kllls[self.showing, 1] - kllls[self.showing, 2])
                    indicatorKL.set_data(self.showing, kllls[self.showing, 2])
                    indicatorL.set_data(self.showing, kllls[self.showing, 1])

                    X, S, Z, theta = self._debug_filter_params(param_dict[self.showing])
                    Xg, Sg, Zg, thetag = self._debug_filter_params(gradient_dict[self.showing])
#                     Xg, Sg, Zg, thetag = -Xg, -Sg, -Zg, -thetag

                    for i, Xlatent in enumerate(Xlatentplts):
                        Xlatent.set_ydata(X[:, i])
                    Xlatentgrads.set_offsets(np.array([xlatent.ravel(), X.ravel()]).T)
                    Xlatentgrads.set_UVC(Ulatent, Xg)

                    for i, Slatent in enumerate(Slatentplts):
                        Slatent.set_ydata(S[:, i])
                    Slatentgrads.set_offsets(np.array([xlatent.ravel(), S.ravel()]).T)
                    Slatentgrads.set_UVC(Ulatent, Sg)

                    for i, Zlatent in enumerate(Zplts):
                        Zlatent.set_ydata(Z[:, i])
                    Zgrads.set_offsets(np.array([xZ.ravel(), Z.ravel()]).T)
                    Zgrads.set_UVC(UZ, Zg)

                    for p, t in zip(thetaplts, theta):
                        p.set_height(t)
                    thetagrads.set_offsets(np.array([xtheta.ravel(), theta.ravel()]).T)
                    thetagrads.set_UVC(Utheta, thetag)

#                     imkmm.set_data(kmm_dict[self.showing][0])
#                     imkmm.autoscale()
#                     cbarkmm.update_normal(imkmm)
#
#                     imkmmdl.set_data(kmm_dict[self.showing][1])
#                     imkmmdl.autoscale()
#                     cbarkmmdl.update_normal(imkmmdl)

                    ax2.relim()
                    # ax3.relim()
                    ax4.relim()
                    ax5.relim()
                    ax2.autoscale()
                    # ax3.autoscale()
                    ax4.autoscale()
                    ax5.autoscale()

                    [fig.canvas.draw() for fig in figs]
            button_options[0] = 0
            button_options[1] = 0

        def onclick(event):
            if event.inaxes is ax1 and event.button == 1:
                button_options[0] = 1
        def motion(event):
            if button_options[0]:
                button_options[1] = 1

        cidr = figs[0].canvas.mpl_connect('button_release_event', update_plots)
        cidp = figs[0].canvas.mpl_connect('button_press_event', onclick)
        cidd = figs[0].canvas.mpl_connect('motion_notify_event', motion)

        return ax1, ax2, ax3, ax4, ax5 # , ax6, ax7
    def plot_scales(self, hyperparams, 
                    groupnames=None,
                    colors=None, 
                    nonzerothreshold=1E-5,
                    fignum="slbgplvm scales",
                    xlabel="Latent Dimension",
                    ylabel=r"Fraction of $\alpha$"):
        
        ngroups = len(self.covar)
        if colors is None:
            from matplotlib.cm import jet  # @UnresolvedImport
            colors = [jet(float(i) / float(ngroups)) for i in range(ngroups)]
        
        from matplotlib.colors import colorConverter
        dcolors = numpy.apply_along_axis(lambda x: numpy.clip(x-.3,0,1),
                                         0,colorConverter.to_rgba_array(\
                                                colors))
        dcolors[:,-1] = 1.
        
        if groupnames is None:
            groupnames = ["Group {}".format(i+1) for i in range(ngroups)]
        ardparams, completesort, ardnames, ardindices = self.sorteddimensiongroups(hyperparams, nonzerothreshold)
        
        ardparamscumsum = ardparams.cumsum(0)
        
        ardparamscumsum = ardparamscumsum[:,completesort]
        ardnames = ardnames[0,completesort]
        ardindices = ardindices[0,completesort]
        
#        ardparamscumsum[:,ardoff] = ardparamscumsum[:,ardoff[offsort]] 
#        ardparamscumsum[:,ardpriv] = ardparamscumsum[:,ardpriv[privsort]] 
#        ardparamscumsum[:,ardsh] = ardparamscumsum[:,ardsh[shsort]]
        
        import pylab
        pylab.figure(fignum)
        pylab.clf()
        left = numpy.arange(ardparams.shape[1])+.1
        
        pylab.bar(left, ardparamscumsum[0], .8, 0, color=colors[0], 
                  label=groupnames[0])
        for i in range(ngroups-1):
            c = colors[i+1]
            dc = dcolors[i+1]
            pylab.bar(left, 
                      ardparamscumsum[i+1], 
                      .8, 
                      ardparamscumsum[i], 
                      facecolor=c,
                      edgecolor=dc,
                      label = groupnames[i+1])
        
        pylab.xticks(left+.4, ["${}$".format(int(x)) for x in completesort])

        pylab.xlabel(xlabel)
        pylab.ylabel(ylabel)
        
        pylab.xlim(0,ardparams.shape[1])
        
        leg = pylab.legend(loc=2, bbox_to_anchor=(1, 1), 
                           borderaxespad=0., prop={'size':12})
        pylab.draw()
        bbox = leg.get_window_extent()
        bbox2 = bbox.transformed(leg.axes.transAxes.inverted())

        pylab.draw()
        pylab.tight_layout(pad=1.04,rect=(0,0,1-bbox2.bounds[2]+.04,1))
Beispiel #18
0
def drawArrows(ax, edgelist, pos):
    def to_marker_edge(marker_size, marker):
        if marker in "s^>v<d":  # `large` markers need extra space
            return np.sqrt(2 * marker_size) / 2
        else:
            return np.sqrt(marker_size) / 2

    ## func argumuments ##
    edge_color = '#055a8c'

    node_size = 300
    node_shape = "o"

    # Edge line style (default='solid') (solid|dashed|dotted,dashdot)
    style = "solid"

    # size of the arrow head head's length and width  (default=10)
    arrowsize = 10

    # For directed graphs, choose the style of the arrowsheads.
    arrowstyle = "-|>"

    # min_source_margin minimum margin (gap) at the begining of the edge at the source.  (default=0)
    min_source_margin = 0

    # min_target_margin The minimum margin (gap) at the end of the edge at the target. (default=0)
    min_target_margin = 0

    # Line width of edges (default=1.0)
    width = 1.0

    connectionstyle = None

    ########

    edge_pos = np.asarray([(pos[e[0].idx], pos[e[1].idx]) for e in edgelist])

    line_width = width

    # Draw arrows with `matplotlib.patches.FancyarrowPatch`

    arrow_collection = []
    mutation_scale = arrowsize  # scale factor of arrow head

    # FancyArrowPatch doesn't handle color strings
    arrow_colors = colorConverter.to_rgba_array("#008081")

    for i, (src, dst) in enumerate(edge_pos):

        x1, y1 = src
        x2, y2 = dst
        shrink_source = 0  # space from source to tail
        shrink_target = 0  # space from  head to target

        shrink_source = shrink_target = to_marker_edge(node_size, node_shape)

        if shrink_source < min_source_margin: shrink_source = min_source_margin

        if shrink_target < min_target_margin: shrink_target = min_target_margin

        if len(arrow_colors) == len(edge_pos):
            arrow_color = arrow_colors[i]

        elif len(arrow_colors) == 1:
            arrow_color = arrow_colors[0]

        else:  # Cycle through colors
            arrow_color = arrow_colors[i % len(arrow_colors)]

        arrow = FancyArrowPatch((x1, y1), (x2, y2), arrowstyle=arrowstyle, shrinkA=shrink_source, shrinkB=shrink_target,
                                mutation_scale=mutation_scale, color=arrow_color, linewidth=line_width,
                                connectionstyle=connectionstyle, linestyle=style, zorder=1, )  # arrows go behind nodes

        arrow_collection.append(arrow)
        ax.add_patch(arrow)

    if len(edge_pos) > 0:
        # update view
        minx = np.amin(np.ravel(edge_pos[:, :, 0]))
        maxx = np.amax(np.ravel(edge_pos[:, :, 0]))
        miny = np.amin(np.ravel(edge_pos[:, :, 1]))
        maxy = np.amax(np.ravel(edge_pos[:, :, 1]))

        w = maxx - minx
        h = maxy - miny

        padx, pady = 0.05 * w, 0.05 * h
        corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady)

        ax.update_datalim(corners)
    ax.autoscale_view()

    ax.tick_params(axis="both", which="both", bottom=False, left=False, labelbottom=False, labelleft=False, )
Beispiel #19
0
def draw_networkx_edges(G, pos,
                        edgelist=None,
                        width=1.0,
                        edge_color='k',
                        style='solid',
                        alpha=None,
                        arrowstyle='-|>',
                        arrowsize=10,
                        edge_cmap=None,
                        edge_vmin=None,
                        edge_vmax=None,
                        ax=None,
                        arrows=True,
                        label=None,
                        node_size=300,
                        nodelist=None,
                        node_shape="o",
                        connectionstyle=None,
                        **kwds):
    """Draw the edges of the graph G.

    This draws only the edges of the graph G.

    Parameters
    ----------
    G : graph
       A networkx graph

    pos : dictionary
       A dictionary with nodes as keys and positions as values.
       Positions should be sequences of length 2.

    edgelist : collection of edge tuples
       Draw only specified edges(default=G.edges())

    width : float, or array of floats
       Line width of edges (default=1.0)

    edge_color : color or array of colors (default='k')
       Edge color. Can be a single color or a sequence of colors with the same
       length as edgelist. Color can be string, or rgb (or rgba) tuple of
       floats from 0-1. If numeric values are specified they will be
       mapped to colors using the edge_cmap and edge_vmin,edge_vmax parameters.

    style : string
       Edge line style (default='solid') (solid|dashed|dotted,dashdot)

    alpha : float
       The edge transparency (default=None)

    edge_ cmap : Matplotlib colormap
       Colormap for mapping intensities of edges (default=None)

    edge_vmin,edge_vmax : floats
       Minimum and maximum for edge colormap scaling (default=None)

    ax : Matplotlib Axes object, optional
       Draw the graph in the specified Matplotlib axes.

    arrows : bool, optional (default=True)
       For directed graphs, if True draw arrowheads.
       Note: Arrows will be the same color as edges.

    arrowstyle : str, optional (default='-|>')
       For directed graphs, choose the style of the arrow heads.
       See :py:class: `matplotlib.patches.ArrowStyle` for more
       options.

    arrowsize : int, optional (default=10)
       For directed graphs, choose the size of the arrow head head's length and
       width. See :py:class: `matplotlib.patches.FancyArrowPatch` for attribute
       `mutation_scale` for more info.

    connectionstyle : str, optional (default=None)
       Pass the connectionstyle parameter to create curved arc of rounding
       radius rad. For example, connectionstyle='arc3,rad=0.2'.
       See :py:class: `matplotlib.patches.ConnectionStyle` and
       :py:class: `matplotlib.patches.FancyArrowPatch` for more info.

    label : [None| string]
       Label for legend

    Returns
    -------
    matplotlib.collection.LineCollection
        `LineCollection` of the edges

    list of matplotlib.patches.FancyArrowPatch
        `FancyArrowPatch` instances of the directed edges

    Depending whether the drawing includes arrows or not.

    Notes
    -----
    For directed graphs, arrows are drawn at the head end.  Arrows can be
    turned off with keyword arrows=False. Be sure to include `node_size` as a
    keyword argument; arrows are drawn considering the size of nodes.

    Examples
    --------
    >>> G = nx.dodecahedral_graph()
    >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))

    >>> G = nx.DiGraph()
    >>> G.add_edges_from([(1, 2), (1, 3), (2, 3)])
    >>> arcs = nx.draw_networkx_edges(G, pos=nx.spring_layout(G))
    >>> alphas = [0.3, 0.4, 0.5]
    >>> for i, arc in enumerate(arcs):  # change alpha values of arcs
    ...     arc.set_alpha(alphas[i])

    Also see the NetworkX drawing examples at
    https://networkx.github.io/documentation/latest/auto_examples/index.html

    See Also
    --------
    draw()
    draw_networkx()
    draw_networkx_nodes()
    draw_networkx_labels()
    draw_networkx_edge_labels()
    """
    try:
        import matplotlib
        import matplotlib.pyplot as plt
        import matplotlib.cbook as cb
        from matplotlib.colors import colorConverter, Colormap, Normalize
        from matplotlib.collections import LineCollection
        from matplotlib.patches import FancyArrowPatch
        import numpy as np
    except ImportError:
        raise ImportError("Matplotlib required for draw()")
    except RuntimeError:
        print("Matplotlib unable to open display")
        raise

    if ax is None:
        ax = plt.gca()

    if edgelist is None:
        edgelist = list(G.edges())

    if not edgelist or len(edgelist) == 0:  # no edges!
        return None

    if nodelist is None:
        nodelist = list(G.nodes())

    # FancyArrowPatch handles color=None different from LineCollection
    if edge_color is None:
        edge_color = 'k'

    # set edge positions
    edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist])

    # Check if edge_color is an array of floats and map to edge_cmap.
    # This is the only case handled differently from matplotlib
    if cb.iterable(edge_color) and (len(edge_color) == len(edge_pos)) \
        and np.alltrue([isinstance(c,Number) for c in edge_color]):
            if edge_cmap is not None:
                assert(isinstance(edge_cmap, Colormap))
            else:
                edge_cmap = plt.get_cmap()
            if edge_vmin is None:
                edge_vmin = min(edge_color)
            if edge_vmax is None:
                edge_vmax = max(edge_color)
            color_normal = Normalize(vmin=edge_vmin, vmax=edge_vmax)
            edge_color = [edge_cmap(color_normal(e)) for e in edge_color]

    if (not G.is_directed() or not arrows):
        edge_collection = LineCollection(edge_pos,
                                         colors=edge_color,
                                         linewidths=width,
                                         antialiaseds=(1,),
                                         linestyle=style,
                                         transOffset=ax.transData,
                                         alpha=alpha
                                         )

        edge_collection.set_zorder(1)  # edges go behind nodes
        edge_collection.set_label(label)
        ax.add_collection(edge_collection)

        return edge_collection

    arrow_collection = None

    if G.is_directed() and arrows:
        # Note: Waiting for someone to implement arrow to intersection with
        # marker.  Meanwhile, this works well for polygons with more than 4
        # sides and circle.

        def to_marker_edge(marker_size, marker):
            if marker in "s^>v<d":  # `large` markers need extra space
                return np.sqrt(2 * marker_size) / 2
            else:
                return np.sqrt(marker_size) / 2

        # Draw arrows with `matplotlib.patches.FancyarrowPatch`
        arrow_collection = []
        mutation_scale = arrowsize  # scale factor of arrow head

        # FancyArrowPatch doesn't handle color strings
        arrow_colors = colorConverter.to_rgba_array(edge_color,alpha)
        for i, (src, dst) in enumerate(edge_pos):
            x1, y1 = src
            x2, y2 = dst
            shrink_source = 0  # space from source to tail
            shrink_target = 0  # space from  head to target
            if cb.iterable(node_size):  # many node sizes
                src_node, dst_node = edgelist[i][:2]
                index_node = nodelist.index(dst_node)
                marker_size = node_size[index_node]
                shrink_target = to_marker_edge(marker_size, node_shape)
            else:
                shrink_target = to_marker_edge(node_size, node_shape)

            if cb.iterable(arrow_colors):
                if len(arrow_colors) == len(edge_pos):
                    arrow_color = arrow_colors[i]
                elif len(arrow_colors)==1:
                    arrow_color = arrow_colors[0]
                else: # Cycle through colors
                    arrow_color =  arrow_colors[i%len(arrow_colors)]
            else:
                arrow_color = edge_color

            if cb.iterable(width):
                if len(width) == len(edge_pos):
                    line_width = width[i]
                else:
                    line_width = width[i%len(width)]
            else:
                line_width = width

            arrow = FancyArrowPatch((x1, y1), (x2, y2),
                                    arrowstyle=arrowstyle,
                                    shrinkA=shrink_source,
                                    shrinkB=shrink_target,
                                    mutation_scale=mutation_scale,
                                    color=arrow_color,
                                    linewidth=line_width,
                                    connectionstyle=connectionstyle,
                                    zorder=1)  # arrows go behind nodes

            # There seems to be a bug in matplotlib to make collections of
            # FancyArrowPatch instances. Until fixed, the patches are added
            # individually to the axes instance.
            arrow_collection.append(arrow)
            ax.add_patch(arrow)

    # update view
    minx = np.amin(np.ravel(edge_pos[:, :, 0]))
    maxx = np.amax(np.ravel(edge_pos[:, :, 0]))
    miny = np.amin(np.ravel(edge_pos[:, :, 1]))
    maxy = np.amax(np.ravel(edge_pos[:, :, 1]))

    w = maxx - minx
    h = maxy - miny
    padx,  pady = 0.05 * w, 0.05 * h
    corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady)
    ax.update_datalim(corners)
    ax.autoscale_view()

    plt.tick_params(
        axis='both',
        which='both',
        bottom=False,
        left=False,
        labelbottom=False,
        labelleft=False)

    return arrow_collection