Exemple #1
0
    def get_rgba(self, tex, fontsize=10, dpi=80, rgb=(0, 0, 0)):
        """
        Return tex string as an rgba array
        """
        # dvipng assumes a constant background, whereas we want to
        # overlay these rasters with antialiasing over arbitrary
        # backgrounds that may have other figure elements under them.
        # When you set dvipng -bg Transparent, it actually makes the
        # alpha channel 1 and does the background compositing and
        # antialiasing itself and puts the blended data in the rgb
        # channels.  So what we do is extract the alpha information
        # from the red channel, which is a blend of the default dvipng
        # background (white) and foreground (black).  So the amount of
        # red (or green or blue for that matter since white and black
        # blend to a grayscale) is the alpha intensity.  Once we
        # extract the correct alpha information, we assign it to the
        # alpha channel properly and let the users pick their rgb.  In
        # this way, we can overlay tex strings on arbitrary
        # backgrounds with antialiasing
        #
        # red = alpha*red_foreground + (1-alpha)*red_background

        # Since the foreground is black (0) and the background is
        # white (1) this reduces to red = 1-alpha or alpha = 1-red

        # assuming standard 10pt design size space
        dpi = fontsize / 10.0 * dpi

        r, g, b = rgb
        key = tex, dpi, tuple(rgb)
        Z = self.arrayd.get(key)

        if Z is None:
            # force=True to skip cacheing while debugging
            pngfile = self.make_png(tex, dpi, force=False)
            X = readpng(pngfile)

            vers = self.get_dvipng_version()
            if vers < '1.6':
                alpha = sqrt(1 - X[:, :, 0])
            else:
                # 1.6 has the alpha channel right
                alpha = sqrt(X[:, :, -1])

            #from matplotlib.mlab import prctile
            #print 'ptile', prctile(ravel(X[:,:,0])), prctile(ravel(X[:,:,-1]))

            Z = zeros(X.shape, Float)
            Z[:, :, 0] = r
            Z[:, :, 1] = g
            Z[:, :, 2] = b
            Z[:, :, 3] = alpha
            #im = fromarray(Z, 1)

            self.arrayd[key] = Z
        return Z
Exemple #2
0
    def get_rgba(self, tex, fontsize=10, dpi=80, rgb=(0,0,0)):
        """
        Return tex string as an rgba array
        """
        # dvipng assumes a constant background, whereas we want to
        # overlay these rasters with antialiasing over arbitrary
        # backgrounds that may have other figure elements under them.
        # When you set dvipng -bg Transparent, it actually makes the
        # alpha channel 1 and does the background compositing and
        # antialiasing itself and puts the blended data in the rgb
        # channels.  So what we do is extract the alpha information
        # from the red channel, which is a blend of the default dvipng
        # background (white) and foreground (black).  So the amount of
        # red (or green or blue for that matter since white and black
        # blend to a grayscale) is the alpha intensity.  Once we
        # extract the correct alpha information, we assign it to the
        # alpha channel properly and let the users pick their rgb.  In
        # this way, we can overlay tex strings on arbitrary
        # backgrounds with antialiasing
        #
        # red = alpha*red_foreground + (1-alpha)*red_background

        # Since the foreground is black (0) and the background is
        # white (1) this reduces to red = 1-alpha or alpha = 1-red
        
        # assuming standard 10pt design size space
        dpi = fontsize/10.0 * dpi
        
        r,g,b = rgb
        key = tex, dpi, tuple(rgb)
        Z = self.arrayd.get(key)

        if Z is None:
            # force=True to skip cacheing while debugging
            pngfile = self.make_png(tex, dpi, force=False) 
            X = readpng(pngfile)

            vers = self.get_dvipng_version()
            if vers<'1.6':
                alpha = sqrt(1-X[:,:,0])
            else:
                # 1.6 has the alpha channel right
                alpha = sqrt(X[:,:,-1])
            
            #from matplotlib.mlab import prctile
            #print 'ptile', prctile(ravel(X[:,:,0])), prctile(ravel(X[:,:,-1]))

            Z = zeros(X.shape, Float)
            Z[:,:,0] = r
            Z[:,:,1] = g
            Z[:,:,2] = b
            Z[:,:,3] = alpha
            #im = fromarray(Z, 1)
               
            self.arrayd[key] = Z
        return Z
Exemple #3
0
 def over_line(line):
     # can't use the line bbox because it covers the entire extent
     # of the line
     xdata = line.transx.positions(line.get_xdata())
     ydata = line.transy.positions(line.get_ydata())
     distances = sqrt((x - xdata)**2 + (y - ydata)**2)
     return min(distances) < epsilon
Exemple #4
0
 def over_line(line):
     # can't use the line bbox because it covers the entire extent
     # of the line
     xdata = line.transx.positions(line.get_xdata())
     ydata = line.transy.positions(line.get_ydata())
     distances = sqrt((x-xdata)**2 + (y-ydata)**2)
     return min(distances)<epsilon
Exemple #5
0
 def over_line(line):
     # can't use the line bbox because it covers the entire extent
     # of the line
     trans = line.get_transform()
     xdata, ydata = trans.numerix_x_y(line.get_xdata(), line.get_ydata())
     distances = sqrt((x - xdata) ** 2 + (y - ydata) ** 2)
     return amin(distances) < epsilon
Exemple #6
0
 def over_line(line):
     # can't use the line bbox because it covers the entire extent
     # of the line
     trans = line.get_transform()
     xdata, ydata = trans.numerix_x_y(line.get_xdata(),
                                      line.get_ydata())
     distances = sqrt((x - xdata)**2 + (y - ydata)**2)
     return min(distances) < epsilon
Exemple #7
0
    def points(self,npoints):
        """
        compute arrays of npoints equally spaced
        intermediate points along the great circle.

        input parameter npoints is the number of points
        to compute.

        Returns lons, lats (lists with longitudes and latitudes
        of intermediate points in degrees).

        For example npoints=10 will return arrays lons,lats of 10
        equally spaced points along the great circle.
        """
        # must ask for at least 2 points.
        if npoints <= 1:
            raise ValueError,'npoints must be greater than 1'
        elif npoints == 2:
            return [math.degrees(self.lon1),math.degrees(self.lon2)],[math.degrees(self.lat1),math.degrees(self.lat2)]
        # can't do it if endpoints are antipodal, since
        # route is undefined.
        if self.antipodal:
            raise ValueError,'cannot compute intermediate points on a great circle whose endpoints are antipodal'
        d = self.gcarclen
        delta = 1.0/(npoints-1)
        f = delta*NX.arange(npoints) # f=0 is point 1, f=1 is point 2.
        incdist = self.distance/(npoints-1)
        lat1 = self.lat1
        lat2 = self.lat2
        lon1 = self.lon1
        lon2 = self.lon2
        # perfect sphere, use great circle formula
        if self.f == 0.:
            A = NX.sin((1-f)*d)/math.sin(d)
            B = NX.sin(f*d)/math.sin(d)
            x = A*math.cos(lat1)*math.cos(lon1)+B*math.cos(lat2)*math.cos(lon2)
            y = A*math.cos(lat1)*math.sin(lon1)+B*math.cos(lat2)*math.sin(lon2)
            z = A*math.sin(lat1)               +B*math.sin(lat2)
            lats=NX.arctan2(z,NX.sqrt(x**2+y**2))
            lons=NX.arctan2(y,x)
            lons = map(math.degrees,lons.tolist())
            lats = map(math.degrees,lats.tolist())
        # use ellipsoid formulas
        else:
            latpt = self.lat1
            lonpt = self.lon1
            azimuth = self.azimuth12
            lons = [math.degrees(lonpt)]
            lats = [math.degrees(latpt)]
            for n in range(npoints-2):
                latptnew,lonptnew,alpha21=vinc_pt(self.f,self.a,latpt,lonpt,azimuth,incdist) 
                d,azimuth,a21=vinc_dist(self.f,self.a,latptnew,lonptnew,lat2,lon2) 
                lats.append(math.degrees(latptnew))
                lons.append(math.degrees(lonptnew))
                latpt = latptnew; lonpt = lonptnew
            lons.append(math.degrees(self.lon2))
            lats.append(math.degrees(self.lat2))
        return lons,lats
Exemple #8
0
 def onpress(self, event):
     if event.inaxes != self.ax: return
     if event.button!=1: return
     # click location in screen coords
     x, y = nx.array((event.x, event.y))
     tx, ty = event.inaxes.transData.numerix_x_y(self.xs, self.ys)
     d = nx.sqrt((x-tx)**2 + (y-ty)**2)
     ind = nx.nonzero(d<5)
     for i in ind:
         self.pnts[i].plotraw()
Exemple #9
0
 def onpress(self, event):
     if event.inaxes != self.ax: return
     if event.button != 1: return
     # click location in screen coords
     x, y = nx.array((event.x, event.y))
     tx, ty = event.inaxes.transData.numerix_x_y(self.xs, self.ys)
     d = nx.sqrt((x - tx)**2 + (y - ty)**2)
     ind = nx.nonzero(d < 5)
     for i in ind:
         self.pnts[i].plotraw()
Exemple #10
0
    def get_rgba(self, tex, fontsize=None, rgb=(0,0,0)):
        """
        Return tex string as an rgba array
        """

        # dvipng assumes a constant background, whereas we want to
        # overlay these rasters with antialiasing over arbitrary
        # backgrounds that may have other figure elements under them.
        # When you set dvipng -bg Transparent, it actually makes the
        # alpha channel 1 and does the background compositing and
        # antialiasing itself and puts the blended data in the rgb
        # channels.  So what we do is extract the alpha information
        # from the red channel, which is a blend of the default dvipng
        # background (white) and foreground (black).  So the amount of
        # red (or green or blue for that matter since white and black
        # blend to a grayscale) is the alpha intensity.  Once we
        # extract the correct alpha information, we assign it to the
        # alpha channel properly and let the users pick their rgb.  In
        # this way, we can overlay tex strings on arbitrary
        # backgrounds with antialiasing
        #
        # red = alpha*red_foreground + (1-alpha)*red_background

        # Since the foreground is black (0) and the background is
        # white (1) this reduces to red = 1-alpha or alpha = 1-red
        if not fontsize: fontsize = rcParams['font.size']
        r,g,b = rgb
        key = tex, fontsize, tuple(rgb)
        Z = self.arrayd.get(key)
        
        if Z is None:
            # force=True to skip cacheing while debugging
            pngfile = self.make_png(tex, fontsize, force=False)
            X = readpng(pngfile)
            vers = self.get_dvipng_version()
            #print 'dvipng version', vers
            if vers<'1.6' or rcParams['text.dvipnghack']:
                # hack the alpha channel as described in comment above
                alpha = sqrt(1-X[:,:,0])
            else:
                alpha = X[:,:,-1]
            

            Z = zeros(X.shape, Float)
            Z[:,:,0] = r
            Z[:,:,1] = g
            Z[:,:,2] = b
            Z[:,:,3] = alpha
               
            self.arrayd[key] = Z

        return Z
Exemple #11
0
    def get_rgba(self, tex, fontsize=None, rgb=(0, 0, 0)):
        """
        Return tex string as an rgba array
        """

        # dvipng assumes a constant background, whereas we want to
        # overlay these rasters with antialiasing over arbitrary
        # backgrounds that may have other figure elements under them.
        # When you set dvipng -bg Transparent, it actually makes the
        # alpha channel 1 and does the background compositing and
        # antialiasing itself and puts the blended data in the rgb
        # channels.  So what we do is extract the alpha information
        # from the red channel, which is a blend of the default dvipng
        # background (white) and foreground (black).  So the amount of
        # red (or green or blue for that matter since white and black
        # blend to a grayscale) is the alpha intensity.  Once we
        # extract the correct alpha information, we assign it to the
        # alpha channel properly and let the users pick their rgb.  In
        # this way, we can overlay tex strings on arbitrary
        # backgrounds with antialiasing
        #
        # red = alpha*red_foreground + (1-alpha)*red_background

        # Since the foreground is black (0) and the background is
        # white (1) this reduces to red = 1-alpha or alpha = 1-red
        if not fontsize: fontsize = rcParams['font.size']
        r, g, b = rgb
        key = tex, fontsize, tuple(rgb)
        Z = self.arrayd.get(key)

        if Z is None:
            # force=True to skip cacheing while debugging
            pngfile = self.make_png(tex, fontsize, force=False)
            X = readpng(pngfile)
            vers = self.get_dvipng_version()
            #print 'dvipng version', vers
            if vers < '1.6' or rcParams['text.dvipnghack']:
                # hack the alpha channel as described in comment above
                alpha = sqrt(1 - X[:, :, 0])
            else:
                alpha = X[:, :, -1]

            Z = zeros(X.shape, Float)
            Z[:, :, 0] = r
            Z[:, :, 1] = g
            Z[:, :, 2] = b
            Z[:, :, 3] = alpha

            self.arrayd[key] = Z

        return Z
Exemple #12
0
    def get_ind_under_point(self, event):
        'get the index of the vertex under point if within epsilon tolerance'
        x, y = zip(*self.poly.verts)

        # display coords
        xt, yt = self.poly.get_transform().numerix_x_y(x, y)
        d = sqrt((xt - event.x)**2 + (yt - event.y)**2)
        indseq = nonzero(equal(d, amin(d)))
        ind = indseq[0]

        if d[ind] >= self.epsilon:
            ind = None

        return ind
Exemple #13
0
    def get_ind_under_point(self, event):
        'get the index of the vertex under point if within epsilon tolerance'
        x, y = zip(*self.poly.verts)
        
        # display coords        
        xt, yt = self.poly.get_transform().numerix_x_y(x, y)
        d = sqrt((xt-event.x)**2 + (yt-event.y)**2)
        indseq = nonzero(equal(d, amin(d)))
        ind = indseq[0]

        if d[ind]>=self.epsilon:
            ind = None

        return ind
Exemple #14
0
    def points(self, npoints):
        """
        compute arrays of npoints equally spaced
        intermediate points along the great circle.

        input parameter npoints is the number of points
        to compute.

        Returns lons, lats (lists with longitudes and latitudes
        of intermediate points in degrees).

        For example npoints=10 will return arrays lons,lats of 10
        equally spaced points along the great circle.
        """
        # must ask for at least 2 points.
        if npoints <= 1:
            raise ValueError, 'npoints must be greater than 1'
        elif npoints == 2:
            return [math.degrees(self.lon1),
                    math.degrees(self.lon2)
                    ], [math.degrees(self.lat1),
                        math.degrees(self.lat2)]
        # can't do it if endpoints are antipodal, since
        # route is undefined.
        if self.antipodal:
            raise ValueError, 'cannot compute intermediate points on a great circle whose endpoints are antipodal'
        d = self.gcarclen
        delta = 1.0 / (npoints - 1)
        f = delta * NX.arange(npoints)  # f=0 is point 1, f=1 is point 2.
        incdist = self.distance / (npoints - 1)
        lat1 = self.lat1
        lat2 = self.lat2
        lon1 = self.lon1
        lon2 = self.lon2
        # perfect sphere, use great circle formula
        if self.f == 0.:
            A = NX.sin((1 - f) * d) / math.sin(d)
            B = NX.sin(f * d) / math.sin(d)
            x = A * math.cos(lat1) * math.cos(lon1) + B * math.cos(
                lat2) * math.cos(lon2)
            y = A * math.cos(lat1) * math.sin(lon1) + B * math.cos(
                lat2) * math.sin(lon2)
            z = A * math.sin(lat1) + B * math.sin(lat2)
            lats = NX.arctan2(z, NX.sqrt(x**2 + y**2))
            lons = NX.arctan2(y, x)
            lons = map(math.degrees, lons.tolist())
            lats = map(math.degrees, lats.tolist())
        # use ellipsoid formulas
        else:
            latpt = self.lat1
            lonpt = self.lon1
            azimuth = self.azimuth12
            lons = [math.degrees(lonpt)]
            lats = [math.degrees(latpt)]
            for n in range(npoints - 2):
                latptnew, lonptnew, alpha21 = vinc_pt(self.f, self.a, latpt,
                                                      lonpt, azimuth, incdist)
                d, azimuth, a21 = vinc_dist(self.f, self.a, latptnew, lonptnew,
                                            lat2, lon2)
                lats.append(math.degrees(latptnew))
                lons.append(math.degrees(lonptnew))
                latpt = latptnew
                lonpt = lonptnew
            lons.append(math.degrees(self.lon2))
            lats.append(math.degrees(self.lat2))
        return lons, lats
Exemple #15
0
from matplotlib.mlab import linspace, meshgrid
import matplotlib.numerix as nx
from pylab import figure,show

n = 56
x = linspace(-1.5,1.5,n)
X,Y = meshgrid(x,x);
Qx = nx.cos(Y) - nx.cos(X)
Qz = nx.sin(Y) + nx.sin(X)
Qx = (Qx + 1.1)
Z = nx.sqrt(X**2 + Y**2)/5;
Z = (Z - nx.mlab.amin(Z)) / (nx.mlab.amax(Z) - nx.mlab.amin(Z))

fig = figure()
ax = fig.add_subplot(111)
ax.pcolormesh(Qx,Qz,Z)
show()
Exemple #16
0
with some restrictions.
"""

from matplotlib.mlab import linspace, meshgrid
import matplotlib.numerix as nx
from pylab import figure,show
import matplotlib.numerix.ma as ma
from matplotlib import cm, colors

n = 56
x = linspace(-1.5,1.5,n)
X,Y = meshgrid(x,x);
Qx = nx.cos(Y) - nx.cos(X)
Qz = nx.sin(Y) + nx.sin(X)
Qx = (Qx + 1.1)
Z = nx.sqrt(X**2 + Y**2)/5;
Z = (Z - nx.mlab.amin(Z)) / (nx.mlab.amax(Z) - nx.mlab.amin(Z))

# The color array can include masked values:
Zm = ma.masked_where(nx.fabs(Qz) < 0.5*nx.mlab.amax(Qz), Z)


fig = figure()
ax = fig.add_subplot(121)
ax.pcolormesh(Qx,Qz,Z)
ax.set_title('Without masked values')

ax = fig.add_subplot(122)
#  You can control the color of the masked region:
#cmap = cm.jet
#cmap.set_bad('r', 1.0)
from pylab import figure, show
import matplotlib.numerix as nx
from matplotlib.image import NonUniformImage

x = nx.arange(-4, 4, 0.005)
y = nx.arange(-4, 4, 0.005)
print 'Size %d points' % (len(x) * len(y))
z = nx.sqrt(x[nx.NewAxis, :]**2 + y[:, nx.NewAxis]**2)

fig = figure()
ax = fig.add_subplot(111)
im = NonUniformImage(ax, extent=(-4, 4, -4, 4))
im.set_data(x, y, z)
ax.images.append(im)
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)

fig2 = figure()
ax = fig2.add_subplot(111)
x2 = x**3
im = NonUniformImage(ax, extent=(-64, 64, -4, 4))
im.set_data(x2, y, z)
ax.images.append(im)
ax.set_xlim(-64, 64)
ax.set_ylim(-4, 4)
show()
Exemple #18
0
from pylab import figure, show
import matplotlib.numerix as nx
from matplotlib.image import NonUniformImage

x = nx.arange(-4, 4, 0.005)
y = nx.arange(-4, 4, 0.005)
print "Size %d points" % (len(x) * len(y))
z = nx.sqrt(x[nx.NewAxis, :] ** 2 + y[:, nx.NewAxis] ** 2)

fig = figure()
ax = fig.add_subplot(111)
im = NonUniformImage(ax, extent=(-4, 4, -4, 4))
im.set_data(x, y, z)
ax.images.append(im)
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)

fig2 = figure()
ax = fig2.add_subplot(111)
x2 = x ** 3
im = NonUniformImage(ax, extent=(-64, 64, -4, 4))
im.set_data(x2, y, z)
ax.images.append(im)
ax.set_xlim(-64, 64)
ax.set_ylim(-4, 4)
show()
Exemple #19
0
def draw_networkx_edges(G, pos,
                        edgelist=None,
                        width=1.0,
                        edge_color='k',
                        style='solid',
                        alpha=1.0,
                        edge_cmap=None,
                        edge_vmin=None,
                        edge_vmax=None, 
                        ax=None,
                        arrows=True,
                        **kwds):
    """Draw the edges of the graph G

    This draws only the edges of the graph G.

    pos is a dictionary keyed by vertex with a two-tuple
    of x-y positions as the value.
    See networkx_v099.layout for functions that compute node positions.

    edgelist is an optional list of the edges in G to be drawn.
    If provided, only the edges in edgelist will be drawn. 

    edgecolor can be a list of matplotlib color letters such as 'k' or
    'b' that lists the color of each edge; the list must be ordered in
    the same way as the edge list. Alternatively, this list can contain
    numbers and those number are mapped to a color scale using the color
    map edge_cmap.
    
    For directed graphs, "arrows" (actually just thicker stubs) are drawn
    at the head end.  Arrows can be turned off with keyword arrows=False.

    See draw_networkx_v099 for the list of other optional parameters.

    """
    if ax is None:
        ax=matplotlib.pylab.gca()

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

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

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

    if not cb.iterable(width):
        lw = (width,)
    else:
        lw = width

    if not cb.is_string_like(edge_color) \
           and cb.iterable(edge_color) \
           and len(edge_color)==len(edge_pos):
        if matplotlib.numerix.alltrue([cb.is_string_like(c) 
                                       for c in edge_color]):
            # (should check ALL elements)
            # list of color letters such as ['k','r','k',...]
            edge_colors = tuple([colorConverter.to_rgba(c,alpha) 
                                 for c in edge_color])
        elif matplotlib.numerix.alltrue([not cb.is_string_like(c) 
                                         for c in edge_color]):
            # numbers (which are going to be mapped with a colormap)
            edge_colors = None
        else:
            raise ValueError('edge_color must consist of either color names or numbers')
    else:
        if len(edge_color)==1:
            edge_colors = ( colorConverter.to_rgba(edge_color, alpha), )
        else:
            raise ValueError('edge_color must be a single color or list of exactly m colors where m is the number or edges')

    edge_collection = LineCollection(edge_pos,
                                colors       = edge_colors,
                                linewidths   = lw,
                                antialiaseds = (1,),
                                linestyle    = style,     
                                transOffset = ax.transData,             
                                )
    edge_collection.set_alpha(alpha)

    # need 0.87.7 or greater for edge colormaps
    mpl_version=matplotlib.__version__
    if mpl_version.endswith('svn'):
        mpl_version=matplotlib.__version__[0:-3]
    if mpl_version.endswith('pre'):
        mpl_version=matplotlib.__version__[0:-3]
    if map(int,mpl_version.split('.'))>=[0,87,7]:
        if edge_colors is None:
            if edge_cmap is not None: assert(isinstance(edge_cmap, Colormap))
            edge_collection.set_array(asarray(edge_color))
            edge_collection.set_cmap(edge_cmap)
            if edge_vmin is not None or edge_vmax is not None:
                edge_collection.set_clim(edge_vmin, edge_vmax)
            else:
                edge_collection.autoscale()
            matplotlib.pylab.sci(edge_collection)

#    else:
#        sys.stderr.write(\
#            """matplotlib version >= 0.87.7 required for colormapped edges.
#        (version %s detected)."""%matplotlib.__version__)
#        raise UserWarning(\
#            """matplotlib version >= 0.87.7 required for colormapped edges.
#        (version %s detected)."""%matplotlib.__version__)

    arrow_collection=None

    if G.directed and arrows:

        # a directed graph hack
        # draw thick line segments at head end of edge
        # waiting for someone else to implement arrows that will work 
        arrow_colors = ( colorConverter.to_rgba('k', alpha), )
        a_pos=[]
        p=1.0-0.25 # make head segment 25 percent of edge length
        for src,dst in edge_pos:
            x1,y1=src
            x2,y2=dst
            dx=x2-x1 # x offset
            dy=y2-y1 # y offset
            d=sqrt(float(dx**2+dy**2)) # length of edge
            if d==0: # source and target at same position
                continue
            if dx==0: # vertical edge
                xa=x2
                ya=dy*p+y1
            if dy==0: # horizontal edge
                ya=y2
                xa=dx*p+x1
            else:
                theta=arctan2(dy,dx)
                xa=p*d*cos(theta)+x1
                ya=p*d*sin(theta)+y1
                
            a_pos.append(((xa,ya),(x2,y2)))

        arrow_collection = LineCollection(a_pos,
                                colors       = arrow_colors,
                                linewidths   = [4*ww for ww in lw],
                                antialiaseds = (1,),
                                transOffset = ax.transData,             
                                )
        
    # update view        
    minx = amin(ravel(edge_pos[:,:,0]))
    maxx = amax(ravel(edge_pos[:,:,0]))
    miny = amin(ravel(edge_pos[:,:,1]))
    maxy = amax(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()

    edge_collection.set_zorder(1) # edges go behind nodes            
    ax.add_collection(edge_collection)
    if arrow_collection:
        arrow_collection.set_zorder(1) # edges go behind nodes            
        ax.add_collection(arrow_collection)


    return edge_collection