Exemplo n.º 1
0
Arquivo: line.py Projeto: yjjcc/sage
    def _render_on_subplot(self, subplot):
        """
        Render this line on a matplotlib subplot.

        INPUT:

        - ``subplot`` -- a matplotlib subplot

        EXAMPLES:

        This implicitly calls this function::

            sage: line([(1,2), (3,-4), (2, 5), (1,2)])
            Graphics object consisting of 1 graphics primitive
        """
        import matplotlib.lines as lines
        options = dict(self.options())
        for o in ('alpha', 'legend_color', 'legend_label', 'linestyle',
                  'rgbcolor', 'thickness'):
            if o in options:
                del options[o]
        p = lines.Line2D(self.xdata, self.ydata, **options)
        options = self.options()
        a = float(options['alpha'])
        p.set_alpha(a)
        p.set_linewidth(float(options['thickness']))
        p.set_color(to_mpl_color(options['rgbcolor']))
        p.set_label(options['legend_label'])
        # we don't pass linestyle in directly since the drawstyles aren't
        # pulled off automatically.  This (I think) is a bug in matplotlib 1.0.1
        if 'linestyle' in options:
            from sage.plot.misc import get_matplotlib_linestyle
            p.set_linestyle(get_matplotlib_linestyle(options['linestyle'],
                                                     return_type='short'))
        subplot.add_line(p)
Exemplo n.º 2
0
Arquivo: line.py Projeto: bukzor/sage
    def _render_on_subplot(self, subplot):
        """
        Render this line on a matplotlib subplot.

        INPUT:

        - ``subplot`` -- a matplotlib subplot

        EXAMPLES:

        This implicitly calls this function::

            sage: line([(1,2), (3,-4), (2, 5), (1,2)])
            Graphics object consisting of 1 graphics primitive
        """
        import matplotlib.lines as lines
        options = dict(self.options())
        for o in ('alpha', 'legend_color', 'legend_label', 'linestyle',
                  'rgbcolor', 'thickness'):
            if o in options:
                del options[o]
        p = lines.Line2D(self.xdata, self.ydata, **options)
        options = self.options()
        a = float(options['alpha'])
        p.set_alpha(a)
        p.set_linewidth(float(options['thickness']))
        p.set_color(to_mpl_color(options['rgbcolor']))
        p.set_label(options['legend_label'])
        # we don't pass linestyle in directly since the drawstyles aren't
        # pulled off automatically.  This (I think) is a bug in matplotlib 1.0.1
        if 'linestyle' in options:
            from sage.plot.misc import get_matplotlib_linestyle
            p.set_linestyle(get_matplotlib_linestyle(options['linestyle'],
                                                     return_type='short'))
        subplot.add_line(p)
Exemplo n.º 3
0
    def __init__(self, datalist, options):
        """
        Initialize a ``Histogram`` primitive along with
        its options.

        EXAMPLES::

            sage: from sage.plot.histogram import Histogram
            sage: Histogram([10,3,5], {'width':0.7})
            Histogram defined by a data list of size 3
        """
        import numpy as np
        self.datalist = np.asarray(datalist, dtype=float)
        if 'normed' in options:
            from sage.misc.superseded import deprecation
            deprecation(
                25260,
                "the 'normed' option is deprecated. Use 'density' instead.")
        if 'linestyle' in options:
            from sage.plot.misc import get_matplotlib_linestyle
            options['linestyle'] = get_matplotlib_linestyle(
                options['linestyle'], return_type='long')
        if options.get('range', None):
            # numpy.histogram performs type checks on "range" so this must be
            # actual floats
            options['range'] = [float(x) for x in options['range']]
        GraphicPrimitive.__init__(self, options)
Exemplo n.º 4
0
    def _render_on_subplot(self, subplot):
        """
        TESTS::

            sage: A = arc((1,1),3,4,pi/4,(pi,4*pi/3)); A
            Graphics object consisting of 1 graphics primitive
        """
        import matplotlib.patches as patches
        from sage.plot.misc import get_matplotlib_linestyle


        options = self.options()

        p = patches.Arc(
                (self.x,self.y),
                2.*self.r1,
                2.*self.r2,
                fmod(self.angle,2*pi)*(180./pi),
                self.s1*(180./pi),
                self.s2*(180./pi))
        p.set_linewidth(float(options['thickness']))
        a = float(options['alpha'])
        p.set_alpha(a)
        z = int(options.pop('zorder',1))
        p.set_zorder(z)
        c = to_mpl_color(options['rgbcolor'])
        p.set_linestyle(get_matplotlib_linestyle(options['linestyle'],return_type='long'))
        p.set_edgecolor(c)
        subplot.add_patch(p)
Exemplo n.º 5
0
    def _render_on_subplot(self, subplot):
        """
        TESTS::

            sage: C = circle((2,pi), 2, edgecolor='black', facecolor='green', fill=True)
        """
        import matplotlib.patches as patches
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        p = patches.Circle((float(self.x), float(self.y)),
                           float(self.r),
                           clip_on=options['clip'])
        if not options['clip']:
            self._bbox_extra_artists = [p]
        p.set_linewidth(float(options['thickness']))
        p.set_fill(options['fill'])
        a = float(options['alpha'])
        p.set_alpha(a)
        ec = to_mpl_color(options['edgecolor'])
        fc = to_mpl_color(options['facecolor'])
        if 'rgbcolor' in options:
            ec = fc = to_mpl_color(options['rgbcolor'])
        p.set_edgecolor(ec)
        p.set_facecolor(fc)
        p.set_linestyle(
            get_matplotlib_linestyle(options['linestyle'], return_type='long'))
        p.set_label(options['legend_label'])
        z = int(options.pop('zorder', 0))
        p.set_zorder(z)
        subplot.add_patch(p)
Exemplo n.º 6
0
Arquivo: arrow.py Projeto: CETHop/sage
    def _render_on_subplot(self, subplot):
        """
        Render this arrow in a subplot.  This is the key function that
        defines how this arrow graphics primitive is rendered in
        matplotlib's library.

        EXAMPLES::

        This function implicitly ends up rendering this arrow on a matplotlib subplot:
            sage: arrow(path=[[(0,1), (2,-1), (4,5)]])
        """
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        width = float(options['width'])
        head = options.pop('head')
        if head == 0: style = '<|-'
        elif head == 1: style = '-|>'
        elif head == 2: style = '<|-|>'
        else: raise KeyError('head parameter must be one of 0 (start), 1 (end) or 2 (both).')
        arrowsize = float(options.get('arrowsize',5))
        head_width=arrowsize
        head_length=arrowsize*2.0
        color = to_mpl_color(options['rgbcolor'])
        from matplotlib.patches import FancyArrowPatch
        from matplotlib.path import Path
        bpath = Path(self.vertices, self.codes)
        p = FancyArrowPatch(path=bpath,
                            lw=width, arrowstyle='%s,head_width=%s,head_length=%s'%(style,head_width, head_length),
                            fc=color, ec=color)
        p.set_linestyle(get_matplotlib_linestyle(options['linestyle'],return_type='long'))
        p.set_zorder(options['zorder'])
        p.set_label(options['legend_label'])
        subplot.add_patch(p)
        return p
Exemplo n.º 7
0
    def _render_on_subplot(self, subplot):
        """
        Render this line on a matplotlib subplot.

        INPUT:

        - ``subplot`` -- a matplotlib subplot

        EXAMPLES:

        This implicitly calls this function::

            sage: line([(1,2), (3,-4), (2, 5), (1,2)])
        """
        import matplotlib.lines as lines

        options = dict(self.options())
        for o in ("alpha", "legend_color", "legend_label", "linestyle", "rgbcolor", "thickness"):
            if o in options:
                del options[o]
        p = lines.Line2D(self.xdata, self.ydata, **options)
        options = self.options()
        a = float(options["alpha"])
        p.set_alpha(a)
        p.set_linewidth(float(options["thickness"]))
        p.set_color(to_mpl_color(options["rgbcolor"]))
        p.set_label(options["legend_label"])
        # we don't pass linestyle in directly since the drawstyles aren't
        # pulled off automatically.  This (I think) is a bug in matplotlib 1.0.1
        if "linestyle" in options:
            from sage.plot.misc import get_matplotlib_linestyle

            p.set_linestyle(get_matplotlib_linestyle(options["linestyle"], return_type="short"))
        subplot.add_line(p)
Exemplo n.º 8
0
    def _render_on_subplot(self, subplot):
        """
        TESTS::

            sage: C = circle((2,pi), 2, edgecolor='black', facecolor='green', fill=True)
        """
        import matplotlib.patches as patches
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        p = patches.Circle((float(self.x), float(self.y)), float(self.r), clip_on=options['clip'])
        if not options['clip']:
            self._bbox_extra_artists=[p]
        p.set_linewidth(float(options['thickness']))
        p.set_fill(options['fill'])
        a = float(options['alpha'])
        p.set_alpha(a)
        ec = to_mpl_color(options['edgecolor'])
        fc = to_mpl_color(options['facecolor'])
        if 'rgbcolor' in options:
            ec = fc = to_mpl_color(options['rgbcolor'])
        p.set_edgecolor(ec)
        p.set_facecolor(fc)
        p.set_linestyle(get_matplotlib_linestyle(options['linestyle'],return_type='long'))
        p.set_label(options['legend_label'])
        z = int(options.pop('zorder', 0))
        p.set_zorder(z)
        subplot.add_patch(p)
Exemplo n.º 9
0
    def _render_on_subplot(self, subplot):
        """
        Render this arrow in a subplot.

        This is the key function that defines how this arrow graphics
        primitive is rendered in matplotlib's library.

        EXAMPLES:

        This function implicitly ends up rendering this arrow on a matplotlib
        subplot::

            sage: arrow(path=[[(0,1), (2,-1), (4,5)]])
            Graphics object consisting of 1 graphics primitive
        """
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        width = float(options['width'])
        head = options.pop('head')
        if head == 0:
            style = '<|-'
        elif head == 1:
            style = '-|>'
        elif head == 2:
            style = '<|-|>'
        else:
            raise KeyError(
                'head parameter must be one of 0 (start), 1 (end) or 2 (both).'
            )
        arrowsize = float(options.get('arrowsize', 5))
        head_width = arrowsize
        head_length = arrowsize * 2.0
        color = to_mpl_color(options['rgbcolor'])
        from matplotlib.patches import FancyArrowPatch
        from matplotlib.path import Path
        bpath = Path(self.vertices, self.codes)
        p = FancyArrowPatch(path=bpath,
                            lw=width,
                            arrowstyle='%s,head_width=%s,head_length=%s' %
                            (style, head_width, head_length),
                            fc=color,
                            ec=color,
                            linestyle=get_matplotlib_linestyle(
                                options['linestyle'], return_type='long'))
        p.set_zorder(options['zorder'])
        p.set_label(options['legend_label'])
        subplot.add_patch(p)
        return p
Exemplo n.º 10
0
    def _render_on_subplot(self, subplot):
        """
        Render this arrow in a subplot.  This is the key function that
        defines how this arrow graphics primitive is rendered in
        matplotlib's library.

        EXAMPLES::

        This function implicitly ends up rendering this arrow on a matplotlib subplot:
            sage: arrow(path=[[(0,1), (2,-1), (4,5)]])
            Graphics object consisting of 1 graphics primitive
        """
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        width = float(options["width"])
        head = options.pop("head")
        if head == 0:
            style = "<|-"
        elif head == 1:
            style = "-|>"
        elif head == 2:
            style = "<|-|>"
        else:
            raise KeyError("head parameter must be one of 0 (start), 1 (end) or 2 (both).")
        arrowsize = float(options.get("arrowsize", 5))
        head_width = arrowsize
        head_length = arrowsize * 2.0
        color = to_mpl_color(options["rgbcolor"])
        from matplotlib.patches import FancyArrowPatch
        from matplotlib.path import Path

        bpath = Path(self.vertices, self.codes)
        p = FancyArrowPatch(
            path=bpath,
            lw=width,
            arrowstyle="%s,head_width=%s,head_length=%s" % (style, head_width, head_length),
            fc=color,
            ec=color,
        )
        p.set_linestyle(get_matplotlib_linestyle(options["linestyle"], return_type="long"))
        p.set_zorder(options["zorder"])
        p.set_label(options["legend_label"])
        subplot.add_patch(p)
        return p
Exemplo n.º 11
0
    def __init__(self, datalist, options):
        """
        Initialize a ``Histogram`` primitive along with
        its options.

        EXAMPLES::

            sage: from sage.plot.histogram import Histogram
            sage: Histogram([10,3,5], {'width':0.7})
            Histogram defined by a data list of size 3
        """
        import numpy as np
        self.datalist=np.asarray(datalist,dtype=float)
        if 'linestyle' in options:
            from sage.plot.misc import get_matplotlib_linestyle
            options['linestyle'] = get_matplotlib_linestyle(
                    options['linestyle'], return_type='long')
        GraphicPrimitive.__init__(self, options)
Exemplo n.º 12
0
    def __init__(self, datalist, options):
        """
        Initialize a ``Histogram`` primitive along with
        its options.

        EXAMPLES::

            sage: from sage.plot.histogram import Histogram
            sage: Histogram([10,3,5], {'width':0.7})
            Histogram defined by a data list of size 3
        """
        import numpy as np
        self.datalist = np.asarray(datalist, dtype=float)
        if 'linestyle' in options:
            from sage.plot.misc import get_matplotlib_linestyle
            options['linestyle'] = get_matplotlib_linestyle(
                options['linestyle'], return_type='long')
        GraphicPrimitive.__init__(self, options)
Exemplo n.º 13
0
    def _render_on_subplot(self, subplot):
        """
        Render this Bezier path in a subplot.  This is the key function that
        defines how this Bezier path graphics primitive is rendered in matplotlib's
        library.

        TESTS::

            sage: bezier_path([[(0,1),(.5,0),(1,1)]])
            Graphics object consisting of 1 graphics primitive

        ::

            sage: bezier_path([[(0,1),(.5,0),(1,1),(-3,5)]])
            Graphics object consisting of 1 graphics primitive
        """
        from matplotlib.patches import PathPatch
        from matplotlib.path import Path
        from sage.plot.misc import get_matplotlib_linestyle

        options = dict(self.options())

        del options['alpha']
        del options['thickness']
        del options['rgbcolor']
        del options['zorder']
        del options['fill']
        del options['linestyle']

        bpath = Path(self.vertices, self.codes)
        bpatch = PathPatch(bpath, **options)
        options = self.options()
        bpatch.set_linewidth(float(options['thickness']))
        bpatch.set_fill(options['fill'])
        bpatch.set_zorder(options['zorder'])
        a = float(options['alpha'])
        bpatch.set_alpha(a)
        c = to_mpl_color(options['rgbcolor'])
        bpatch.set_edgecolor(c)
        bpatch.set_facecolor(c)
        bpatch.set_linestyle(
            get_matplotlib_linestyle(options['linestyle'], return_type='long'))
        subplot.add_patch(bpatch)
Exemplo n.º 14
0
    def _render_on_subplot(self, subplot):
        """
        Render this Bezier path in a subplot.  This is the key function that
        defines how this Bezier path graphics primitive is rendered in matplotlib's
        library.

        TESTS::

            sage: bezier_path([[(0,1),(.5,0),(1,1)]])
            Graphics object consisting of 1 graphics primitive

        ::

            sage: bezier_path([[(0,1),(.5,0),(1,1),(-3,5)]])
            Graphics object consisting of 1 graphics primitive
        """
        from matplotlib.patches import PathPatch
        from matplotlib.path import Path
        from sage.plot.misc import get_matplotlib_linestyle

        options = dict(self.options())

        del options['alpha']
        del options['thickness']
        del options['rgbcolor']
        del options['zorder']
        del options['fill']
        del options['linestyle']

        bpath = Path(self.vertices, self.codes)
        bpatch = PathPatch(bpath, **options)
        options = self.options()
        bpatch.set_linewidth(float(options['thickness']))
        bpatch.set_fill(options['fill'])
        bpatch.set_zorder(options['zorder'])
        a = float(options['alpha'])
        bpatch.set_alpha(a)
        c = to_mpl_color(options['rgbcolor'])
        bpatch.set_edgecolor(c)
        bpatch.set_facecolor(c)
        bpatch.set_linestyle(get_matplotlib_linestyle(options['linestyle'], return_type='long'))
        subplot.add_patch(bpatch)
Exemplo n.º 15
0
Arquivo: arc.py Projeto: ProgVal/sage
    def _render_on_subplot(self, subplot):
        """
        TESTS::

            sage: A = arc((1,1),3,4,pi/4,(pi,4*pi/3)); A
            Graphics object consisting of 1 graphics primitive
        """
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()

        p = self._matplotlib_arc()
        p.set_linewidth(float(options['thickness']))
        a = float(options['alpha'])
        p.set_alpha(a)
        z = int(options.pop('zorder', 1))
        p.set_zorder(z)
        c = to_mpl_color(options['rgbcolor'])
        p.set_linestyle(get_matplotlib_linestyle(options['linestyle'],
                                                 return_type='long'))
        p.set_edgecolor(c)
        subplot.add_patch(p)
Exemplo n.º 16
0
    def _render_on_subplot(self, subplot):
        """
        TESTS::

            sage: A = arc((1,1),3,4,pi/4,(pi,4*pi/3)); A
            Graphics object consisting of 1 graphics primitive
        """
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()

        p = self._matplotlib_arc()
        p.set_linewidth(float(options['thickness']))
        a = float(options['alpha'])
        p.set_alpha(a)
        z = int(options.pop('zorder', 1))
        p.set_zorder(z)
        c = to_mpl_color(options['rgbcolor'])
        p.set_linestyle(
            get_matplotlib_linestyle(options['linestyle'], return_type='long'))
        p.set_edgecolor(c)
        subplot.add_patch(p)
Exemplo n.º 17
0
    def _render_on_subplot(self, subplot):
        """
        Render this ellipse in a subplot.  This is the key function that
        defines how this ellipse graphics primitive is rendered in matplotlib's
        library.

        TESTS::

            sage: ellipse((0,0),3,1,pi/6,fill=True,alpha=0.3)
            Graphics object consisting of 1 graphics primitive

        ::

            sage: ellipse((3,2),1,2)
            Graphics object consisting of 1 graphics primitive
        """
        import matplotlib.patches as patches
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        p = patches.Ellipse((self.x, self.y), self.r1 * 2., self.r2 * 2.,
                            self.angle / pi * 180.)
        p.set_linewidth(float(options['thickness']))
        p.set_fill(options['fill'])
        a = float(options['alpha'])
        p.set_alpha(a)
        ec = to_mpl_color(options['edgecolor'])
        fc = to_mpl_color(options['facecolor'])
        if 'rgbcolor' in options:
            ec = fc = to_mpl_color(options['rgbcolor'])
        p.set_edgecolor(ec)
        p.set_facecolor(fc)
        p.set_linestyle(
            get_matplotlib_linestyle(options['linestyle'], return_type='long'))
        p.set_label(options['legend_label'])
        z = int(options.pop('zorder', 0))
        p.set_zorder(z)
        subplot.add_patch(p)
Exemplo n.º 18
0
    def _render_on_subplot(self, subplot):
        """
        Render this ellipse in a subplot.  This is the key function that
        defines how this ellipse graphics primitive is rendered in matplotlib's
        library.

        TESTS::

            sage: ellipse((0,0),3,1,pi/6,fill=True,alpha=0.3)
            Graphics object consisting of 1 graphics primitive

        ::

            sage: ellipse((3,2),1,2)
            Graphics object consisting of 1 graphics primitive
        """
        import matplotlib.patches as patches
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        p = patches.Ellipse(
                (self.x,self.y),
                self.r1*2.,self.r2*2.,self.angle/pi*180.)
        p.set_linewidth(float(options['thickness']))
        p.set_fill(options['fill'])
        a = float(options['alpha'])
        p.set_alpha(a)
        ec = to_mpl_color(options['edgecolor'])
        fc = to_mpl_color(options['facecolor'])
        if 'rgbcolor' in options:
            ec = fc = to_mpl_color(options['rgbcolor'])
        p.set_edgecolor(ec)
        p.set_facecolor(fc)
        p.set_linestyle(get_matplotlib_linestyle(options['linestyle'],return_type='long'))
        p.set_label(options['legend_label'])
        z = int(options.pop('zorder', 0))
        p.set_zorder(z)
        subplot.add_patch(p)
    def _render_on_subplot(self, subplot):
        r"""
        Render this arrow in a subplot.

        This version of the method uses a narrower arrow head,
        which is not customizable by parameters in the Sage class.
        """

        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        head = options.pop('head')
        if head == 0: style = '<|-'
        elif head == 1: style = '-|>'
        elif head == 2: style = '<|-|>'
        else: raise KeyError('head parameter must be one of 0 (start), 1 (end) or 2 (both).')
        style='fancy'
        width = float(options['width'])
        arrowshorten_end = float(options.get('arrowshorten', 0)) / 2.0
        arrowsize = float(options.get('arrowsize', 5))
        #head_width = arrowsize * 0.5
        head_width = arrowsize * 0.7
        tail_width = arrowsize * 0.7
        head_length = arrowsize * 2.0
        color = to_mpl_color(options['rgbcolor'])
        from matplotlib.patches import FancyArrowPatch
        p = FancyArrowPatch((self.xtail, self.ytail), (self.xhead, self.yhead),
                            lw=width,
                            arrowstyle='%s,head_width=%s,head_length=%s,tail_width=%s' % (style, head_width, head_length, tail_width),
                            shrinkA=arrowshorten_end, shrinkB=arrowshorten_end,
                            fc=color, ec=color,
                            linestyle=get_matplotlib_linestyle(options['linestyle'], return_type='long'))
        p.set_zorder(options['zorder'])
        p.set_label(options['legend_label'])

        subplot.add_patch(p)
        return p
Exemplo n.º 20
0
    def _render_on_subplot(self, subplot):
        """
        TESTS:

        A somewhat random plot, but fun to look at::

            sage: x,y = var('x,y')
            sage: contour_plot(x^2-y^3+10*sin(x*y), (x, -4, 4), (y, -4, 4),plot_points=121,cmap='hsv')
            Graphics object consisting of 1 graphics primitive
        """
        from sage.rings.integer import Integer
        options = self.options()
        fill = options['fill']
        contours = options['contours']
        if 'cmap' in options:
            cmap = get_cmap(options['cmap'])
        elif fill or contours is None:
            cmap = get_cmap('gray')
        else:
            if isinstance(contours, (int, Integer)):
                cmap = get_cmap([(i, i, i)
                                 for i in xsrange(0, 1, 1 / contours)])
            else:
                l = Integer(len(contours))
                cmap = get_cmap([(i, i, i) for i in xsrange(0, 1, 1 / l)])

        x0, x1 = float(self.xrange[0]), float(self.xrange[1])
        y0, y1 = float(self.yrange[0]), float(self.yrange[1])

        if isinstance(contours, (int, Integer)):
            contours = int(contours)

        CSF = None
        if fill:
            if contours is None:
                CSF = subplot.contourf(self.xy_data_array,
                                       cmap=cmap,
                                       extent=(x0, x1, y0, y1),
                                       label=options['legend_label'])
            else:
                CSF = subplot.contourf(self.xy_data_array,
                                       contours,
                                       cmap=cmap,
                                       extent=(x0, x1, y0, y1),
                                       extend='both',
                                       label=options['legend_label'])

        linewidths = options.get('linewidths', None)
        if isinstance(linewidths, (int, Integer)):
            linewidths = int(linewidths)
        elif isinstance(linewidths, (list, tuple)):
            linewidths = tuple(int(x) for x in linewidths)

        from sage.plot.misc import get_matplotlib_linestyle
        linestyles = options.get('linestyles', None)
        if isinstance(linestyles, (list, tuple)):
            linestyles = [
                get_matplotlib_linestyle(l, 'long') for l in linestyles
            ]
        else:
            linestyles = get_matplotlib_linestyle(linestyles, 'long')
        if contours is None:
            CS = subplot.contour(self.xy_data_array,
                                 cmap=cmap,
                                 extent=(x0, x1, y0, y1),
                                 linewidths=linewidths,
                                 linestyles=linestyles,
                                 label=options['legend_label'])
        else:
            CS = subplot.contour(self.xy_data_array,
                                 contours,
                                 cmap=cmap,
                                 extent=(x0, x1, y0, y1),
                                 linewidths=linewidths,
                                 linestyles=linestyles,
                                 label=options['legend_label'])
        if options.get('labels', False):
            label_options = options['label_options']
            label_options['fontsize'] = int(label_options['fontsize'])
            if fill and label_options is None:
                label_options['inline'] = False
            subplot.clabel(CS, **label_options)
        if options.get('colorbar', False):
            colorbar_options = options['colorbar_options']
            from matplotlib import colorbar
            cax, kwds = colorbar.make_axes_gridspec(subplot,
                                                    **colorbar_options)
            if CSF is None:
                cb = colorbar.Colorbar(cax, CS, **kwds)
            else:
                cb = colorbar.Colorbar(cax, CSF, **kwds)
                cb.add_lines(CS)
Exemplo n.º 21
0
    def _render_on_subplot(self, subplot):
        """
        TESTS:

        A somewhat random plot, but fun to look at::

            sage: x,y = var('x,y')
            sage: contour_plot(x^2-y^3+10*sin(x*y), (x, -4, 4), (y, -4, 4),plot_points=121,cmap='hsv')
        """
        from sage.rings.integer import Integer
        options = self.options()
        fill = options['fill']
        contours = options['contours']
        if options.has_key('cmap'):
            cmap = get_cmap(options['cmap'])
        elif fill or contours is None:
            cmap = get_cmap('gray')
        else:
            if isinstance(contours, (int, Integer)):
                cmap = get_cmap([(i,i,i) for i in xsrange(0,1,1/contours)])
            else:
                l = Integer(len(contours))
                cmap = get_cmap([(i,i,i) for i in xsrange(0,1,1/l)])

        x0,x1 = float(self.xrange[0]), float(self.xrange[1])
        y0,y1 = float(self.yrange[0]), float(self.yrange[1])

        if isinstance(contours, (int, Integer)):
            contours = int(contours)

        CSF=None
        if fill:
            if contours is None:
                CSF=subplot.contourf(self.xy_data_array, cmap=cmap, extent=(x0,x1,y0,y1), label=options['legend_label'])
            else:
                CSF=subplot.contourf(self.xy_data_array, contours, cmap=cmap, extent=(x0,x1,y0,y1),extend='both', label=options['legend_label'])

        linewidths = options.get('linewidths',None)
        if isinstance(linewidths, (int, Integer)):
            linewidths = int(linewidths)
        elif isinstance(linewidths, (list, tuple)):
            linewidths = tuple(int(x) for x in linewidths)

        from sage.plot.misc import get_matplotlib_linestyle
        linestyles = options.get('linestyles', None)
        if isinstance(linestyles, (list, tuple)):
            linestyles = [get_matplotlib_linestyle(l, 'long') for l in linestyles]
        else:
            linestyles = get_matplotlib_linestyle(linestyles, 'long')
        if contours is None:
            CS = subplot.contour(self.xy_data_array, cmap=cmap, extent=(x0,x1,y0,y1),
                                 linewidths=linewidths, linestyles=linestyles, label=options['legend_label'])
        else:
            CS = subplot.contour(self.xy_data_array, contours, cmap=cmap, extent=(x0,x1,y0,y1),
                            linewidths=linewidths, linestyles=linestyles, label=options['legend_label'])
        if options.get('labels', False):
            label_options = options['label_options']
            label_options['fontsize'] = int(label_options['fontsize'])
            if fill and label_options is None:
                label_options['inline']=False
            subplot.clabel(CS, **label_options)
        if options.get('colorbar', False):
            colorbar_options = options['colorbar_options']
            from matplotlib import colorbar
            cax,kwds=colorbar.make_axes_gridspec(subplot,**colorbar_options)
            if CSF is None:
                cb=colorbar.Colorbar(cax,CS, **kwds)
            else:
                cb=colorbar.Colorbar(cax,CSF, **kwds)
                cb.add_lines(CS)
Exemplo n.º 22
0
    def set_edges(self, **edge_options):
        """
        Sets the edge (or arrow) plotting parameters for the ``GraphPlot`` object.

        This function is called by the constructor but can also be called to make
        updates to the vertex options of an existing ``GraphPlot`` object.  Note
        that the changes are cumulative.

        EXAMPLES::

            sage: g = Graph({}, loops=True, multiedges=True, sparse=True)
            sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: GP = g.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed')
            sage: GP.set_edges(edge_style='solid')
            sage: GP.plot()
            Graphics object consisting of 22 graphics primitives
            sage: GP.set_edges(edge_color='black')
            sage: GP.plot()
            Graphics object consisting of 22 graphics primitives

            sage: d = DiGraph({}, loops=True, multiedges=True, sparse=True)
            sage: d.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: GP = d.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed')
            sage: GP.set_edges(edge_style='solid')
            sage: GP.plot()
            Graphics object consisting of 24 graphics primitives
            sage: GP.set_edges(edge_color='black')
            sage: GP.plot()
            Graphics object consisting of 24 graphics primitives

        TESTS::

            sage: G = Graph("Fooba")
            sage: G.show(edge_colors={'red':[(3,6),(2,5)]})

        Verify that default edge labels are pretty close to being between the vertices
        in some cases where they weren't due to truncating division (:trac:`10124`)::

            sage: test_graphs = graphs.FruchtGraph(), graphs.BullGraph()
            sage: tol = 0.001
            sage: for G in test_graphs:
            ...       E=G.edges()
            ...       for e0, e1, elab in E:
            ...           G.set_edge_label(e0, e1, '%d %d' % (e0, e1))
            ...       gp = G.graphplot(save_pos=True,edge_labels=True)
            ...       vx = gp._plot_components['vertices'][0].xdata
            ...       vy = gp._plot_components['vertices'][0].ydata
            ...       for elab in gp._plot_components['edge_labels']:
            ...           textobj = elab[0]
            ...           x, y, s = textobj.x, textobj.y, textobj.string
            ...           v0, v1 = map(int, s.split())
            ...           vn = vector(((x-(vx[v0]+vx[v1])/2.),y-(vy[v0]+vy[v1])/2.)).norm()
            ...           assert vn < tol

        """
        for arg in edge_options:
            self._options[arg] = edge_options[arg]
        if 'edge_colors' in edge_options:
            self._options['color_by_label'] = False

        # Handle base edge options: thickness, linestyle
        eoptions = {}
        if 'edge_style' in self._options:
            from sage.plot.misc import get_matplotlib_linestyle
            eoptions['linestyle'] = get_matplotlib_linestyle(
                self._options['edge_style'], return_type='long')
        if 'thickness' in self._options:
            eoptions['thickness'] = self._options['thickness']

        # Set labels param to add labels on the fly
        labels = False
        if self._options['edge_labels']:
            labels = True
            self._plot_components['edge_labels'] = []

        # Make dict collection of all edges (keep label and edge color)
        edges_to_draw = {}
        if self._options['color_by_label'] or isinstance(
                self._options['edge_colors'], dict):
            if self._options['color_by_label']:
                edge_colors = self._graph._color_by_label(
                    format=self._options['color_by_label'])
            else:
                edge_colors = self._options['edge_colors']
            for color in edge_colors:
                for edge in edge_colors[color]:
                    key = tuple(sorted([edge[0], edge[1]]))
                    if key == (edge[0], edge[1]): head = 1
                    else: head = 0

                    if len(edge) < 3:
                        label = self._graph.edge_label(edge[0], edge[1])
                        if isinstance(label, list):
                            if key in edges_to_draw:
                                edges_to_draw[key].append(
                                    (label[-1], color, head))
                            else:
                                edges_to_draw[key] = [(label[-1], color, head)]
                            for i in range(len(label) - 1):
                                edges_to_draw[key].append(
                                    (label[-1], color, head))
                    else:
                        label = edge[2]

                    if key in edges_to_draw:
                        edges_to_draw[key].append((label, color, head))
                    else:
                        edges_to_draw[key] = [(label, color, head)]
            # add unspecified edges in (default color black)
            for edge in self._graph.edge_iterator():
                key = tuple(sorted([edge[0], edge[1]]))
                label = edge[2]
                specified = False
                if key in edges_to_draw:
                    for old_label, old_color, old_head in edges_to_draw[key]:
                        if label == old_label:
                            specified = True
                            break
                if not specified:
                    if key == (edge[0], edge[1]): head = 1
                    else: head = 0
                    edges_to_draw[key] = [(label, 'black', head)]
        else:
            for edge in self._graph.edges(sort=True):
                key = tuple(sorted([edge[0], edge[1]]))
                if key == (edge[0], edge[1]): head = 1
                else: head = 0
                if key in edges_to_draw:
                    edges_to_draw[key].append(
                        (edge[2], self._options['edge_color'], head))
                else:
                    edges_to_draw[key] = [(edge[2],
                                           self._options['edge_color'], head)]

        if edges_to_draw:
            self._plot_components['edges'] = []
        else:
            return

        # Check for multi-edges or loops
        if self._arcs or self._loops:
            tmp = edges_to_draw.copy()
            dist = self._options['dist'] * 2.
            loop_size = self._options['loop_size']
            max_dist = self._options['max_dist']
            from sage.functions.all import sqrt
            for (a, b) in tmp:
                if a == b:
                    # Loops
                    distance = dist
                    local_labels = edges_to_draw.pop((a, b))
                    if len(local_labels) * dist > max_dist:
                        distance = float(max_dist) / len(local_labels)
                    curr_loop_size = loop_size
                    for i in range(len(local_labels)):
                        self._plot_components['edges'].append(
                            circle((self._pos[a][0],
                                    self._pos[a][1] - curr_loop_size),
                                   curr_loop_size,
                                   rgbcolor=local_labels[i][1],
                                   **eoptions))
                        if labels:
                            self._plot_components['edge_labels'].append(
                                text(local_labels[i][0],
                                     (self._pos[a][0],
                                      self._pos[a][1] - 2 * curr_loop_size)))
                        curr_loop_size += distance / 4
                elif len(edges_to_draw[(a, b)]) > 1:
                    # Multi-edge
                    local_labels = edges_to_draw.pop((a, b))

                    # Compute perpendicular bisector
                    p1 = self._pos[a]
                    p2 = self._pos[b]
                    M = (
                        (p1[0] + p2[0]) / 2., (p1[1] + p2[1]) / 2.)  # midpoint
                    if not p1[1] == p2[1]:
                        S = float(p1[0] - p2[0]) / (p2[1] - p1[1]
                                                    )  # perp slope
                        y = lambda x: S * x - S * M[0] + M[
                            1]  # perp bisector line

                        # f,g are functions of distance d to determine x values
                        # on line y at d from point M
                        f = lambda d: sqrt(d**2 / (1. + S**2)) + M[0]
                        g = lambda d: -sqrt(d**2 / (1. + S**2)) + M[0]

                        odd_x = f
                        even_x = g
                        if p1[0] == p2[0]:
                            odd_y = lambda d: M[1]
                            even_y = odd_y
                        else:
                            odd_y = lambda x: y(f(x))
                            even_y = lambda x: y(g(x))
                    else:
                        odd_x = lambda d: M[0]
                        even_x = odd_x
                        odd_y = lambda d: M[1] + d
                        even_y = lambda d: M[1] - d

                    # We now have the control points for each bezier curve
                    # in terms of distance parameter d.
                    # Also note that the label for each edge should be drawn at d/2.
                    # (This is because we're using the perp bisectors).
                    distance = dist
                    if len(local_labels) * dist > max_dist:
                        distance = float(max_dist) / len(local_labels)
                    for i in range(len(local_labels) // 2):
                        k = (i + 1.0) * distance
                        if self._arcdigraph:
                            odd_start = self._polar_hack_for_multidigraph(
                                p1, [odd_x(k), odd_y(k)],
                                self._vertex_radius)[0]
                            odd_end = self._polar_hack_for_multidigraph(
                                [odd_x(k), odd_y(k)], p2,
                                self._vertex_radius)[1]
                            even_start = self._polar_hack_for_multidigraph(
                                p1, [even_x(k), even_y(k)],
                                self._vertex_radius)[0]
                            even_end = self._polar_hack_for_multidigraph(
                                [even_x(k), even_y(k)], p2,
                                self._vertex_radius)[1]
                            self._plot_components['edges'].append(
                                arrow(path=[[
                                    odd_start, [odd_x(k), odd_y(k)], odd_end
                                ]],
                                      head=local_labels[2 * i][2],
                                      zorder=1,
                                      rgbcolor=local_labels[2 * i][1],
                                      **eoptions))
                            self._plot_components['edges'].append(
                                arrow(path=[[
                                    even_start, [even_x(k),
                                                 even_y(k)], even_end
                                ]],
                                      head=local_labels[2 * i + 1][2],
                                      zorder=1,
                                      rgbcolor=local_labels[2 * i + 1][1],
                                      **eoptions))
                        else:
                            self._plot_components['edges'].append(
                                bezier_path(
                                    [[p1, [odd_x(k), odd_y(k)], p2]],
                                    zorder=1,
                                    rgbcolor=local_labels[2 * i][1],
                                    **eoptions))
                            self._plot_components['edges'].append(
                                bezier_path(
                                    [[p1, [even_x(k), even_y(k)], p2]],
                                    zorder=1,
                                    rgbcolor=local_labels[2 * i + 1][1],
                                    **eoptions))
                        if labels:
                            j = k / 2.0
                            self._plot_components['edge_labels'].append(
                                text(local_labels[2 * i][0],
                                     [odd_x(j), odd_y(j)]))
                            self._plot_components['edge_labels'].append(
                                text(local_labels[2 * i + 1][0],
                                     [even_x(j), even_y(j)]))
                    if len(local_labels) % 2 == 1:
                        edges_to_draw[(a, b)] = [local_labels[-1]
                                                 ]  # draw line for last odd

        dir = self._graph.is_directed()
        for (a, b) in edges_to_draw:
            if self._arcdigraph:
                C, D = self._polar_hack_for_multidigraph(
                    self._pos[a], self._pos[b], self._vertex_radius)
                self._plot_components['edges'].append(
                    arrow(C,
                          D,
                          rgbcolor=edges_to_draw[(a, b)][0][1],
                          head=edges_to_draw[(a, b)][0][2],
                          **eoptions))
                if labels:
                    self._plot_components['edge_labels'].append(
                        text(str(edges_to_draw[(a, b)][0][0]),
                             [(C[0] + D[0]) / 2., (C[1] + D[1]) / 2.]))
            elif dir:
                self._plot_components['edges'].append(
                    arrow(self._pos[a],
                          self._pos[b],
                          rgbcolor=edges_to_draw[(a, b)][0][1],
                          arrowshorten=self._arrowshorten,
                          head=edges_to_draw[(a, b)][0][2],
                          **eoptions))
            else:
                self._plot_components['edges'].append(
                    line([self._pos[a], self._pos[b]],
                         rgbcolor=edges_to_draw[(a, b)][0][1],
                         **eoptions))
            if labels and not self._arcdigraph:
                self._plot_components['edge_labels'].append(
                    text(str(edges_to_draw[(a, b)][0][0]),
                         [(self._pos[a][0] + self._pos[b][0]) / 2.,
                          (self._pos[a][1] + self._pos[b][1]) / 2.]))
Exemplo n.º 23
0
    def _render_on_subplot(self, subplot):
        r"""
        Render this arrow in a subplot.  This is the key function that
        defines how this arrow graphics primitive is rendered in
        matplotlib's library.

        EXAMPLES:

        This function implicitly ends up rendering this arrow on
        a matplotlib subplot::

            sage: arrow((0,1), (2,-1))
            Graphics object consisting of 1 graphics primitive

        TESTS:

        The length of the ends (shrinkA and shrinkB) should not depend
        on the width of the arrow, because Matplotlib already takes
        this into account. See :trac:`12836`::

            sage: fig = Graphics().matplotlib()
            sage: sp = fig.add_subplot(1,1,1)
            sage: a = arrow((0,0), (1,1))
            sage: b = arrow((0,0), (1,1), width=20)
            sage: p1 = a[0]._render_on_subplot(sp)
            sage: p2 = b[0]._render_on_subplot(sp)
            sage: p1.shrinkA == p2.shrinkA
            True
            sage: p1.shrinkB == p2.shrinkB
            True

        Dashed arrows should have solid arrowheads,
        :trac:`12852`. This test saves the plot of a dashed arrow to
        an EPS file. Within the EPS file, ``stroke`` will be called
        twice: once to draw the line, and again to draw the
        arrowhead. We check that both calls do not occur while the
        dashed line style is enabled::

            sage: a = arrow((0,0), (1,1), linestyle='dashed')
            sage: filename = tmp_filename(ext='.eps')
            sage: a.save(filename=filename)
            sage: with open(filename, 'r') as f:
            ....:     contents = f.read().replace('\n', ' ')
            sage: two_stroke_pattern = r'setdash.*stroke.*stroke.*setdash'
            sage: import re
            sage: two_stroke_re = re.compile(two_stroke_pattern)
            sage: two_stroke_re.search(contents) is None
            True
        """
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        head = options.pop('head')
        if head == 0: style = '<|-'
        elif head == 1: style = '-|>'
        elif head == 2: style = '<|-|>'
        else:
            raise KeyError(
                'head parameter must be one of 0 (start), 1 (end) or 2 (both).'
            )
        width = float(options['width'])
        arrowshorten_end = float(options.get('arrowshorten', 0)) / 2.0
        arrowsize = float(options.get('arrowsize', 5))
        head_width = arrowsize
        head_length = arrowsize * 2.0
        color = to_mpl_color(options['rgbcolor'])
        from matplotlib.patches import FancyArrowPatch
        p = FancyArrowPatch((self.xtail, self.ytail), (self.xhead, self.yhead),
                            lw=width,
                            arrowstyle='%s,head_width=%s,head_length=%s' %
                            (style, head_width, head_length),
                            shrinkA=arrowshorten_end,
                            shrinkB=arrowshorten_end,
                            fc=color,
                            ec=color)
        p.set_linestyle(
            get_matplotlib_linestyle(options['linestyle'], return_type='long'))
        p.set_zorder(options['zorder'])
        p.set_label(options['legend_label'])

        if options['linestyle'] != 'solid':
            # The next few lines work around a design issue in matplotlib. Currently, the specified
            # linestyle is used to draw both the path and the arrowhead.  If linestyle is 'dashed', this
            # looks really odd.  This code is from Jae-Joon Lee in response to a post to the matplotlib mailing
            # list.  See http://sourceforge.net/mailarchive/forum.php?thread_name=CAG%3DuJ%2Bnw2dE05P9TOXTz_zp-mGP3cY801vMH7yt6vgP9_WzU8w%40mail.gmail.com&forum_name=matplotlib-users

            import matplotlib.patheffects as pe

            class CheckNthSubPath(object):
                def __init__(self, patch, n):
                    """
                    creates an callable object that returns True if the provided
                    path is the n-th path from the patch.
                    """
                    self._patch = patch
                    self._n = n

                def get_paths(self, renderer):
                    self._patch.set_dpi_cor(renderer.points_to_pixels(1.))
                    paths, fillables = self._patch.get_path_in_displaycoord()
                    return paths

                def __call__(self, renderer, gc, tpath, affine, rgbFace):
                    path = self.get_paths(renderer)[self._n]
                    vert1, code1 = path.vertices, path.codes
                    import numpy as np

                    return np.array_equal(vert1,
                                          tpath.vertices) and np.array_equal(
                                              code1, tpath.codes)

            class ConditionalStroke(pe.RendererBase):
                def __init__(self, condition_func, pe_list):
                    """
                    path effect that is only applied when the condition_func
                    returns True.
                    """
                    super(ConditionalStroke, self).__init__()
                    self._pe_list = pe_list
                    self._condition_func = condition_func

                def draw_path(self, renderer, gc, tpath, affine, rgbFace):

                    if self._condition_func(renderer, gc, tpath, affine,
                                            rgbFace):
                        for pe1 in self._pe_list:
                            pe1.draw_path(renderer, gc, tpath, affine, rgbFace)

            pe1 = ConditionalStroke(CheckNthSubPath(p, 0), [pe.Stroke()])
            pe2 = ConditionalStroke(CheckNthSubPath(p, 1),
                                    [pe.Stroke(linestyle="solid")])
            p.set_path_effects([pe1, pe2])

        subplot.add_patch(p)
        return p
Exemplo n.º 24
0
    def set_edges(self, **edge_options):
        """
        Sets the edge (or arrow) plotting parameters for the ``GraphPlot`` object.

        This function is called by the constructor but can also be called to make
        updates to the vertex options of an existing ``GraphPlot`` object.  Note
        that the changes are cumulative.

        EXAMPLES::

            sage: g = Graph({}, loops=True, multiedges=True, sparse=True)
            sage: g.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: GP = g.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed')
            sage: GP.set_edges(edge_style='solid')
            sage: GP.plot()
            Graphics object consisting of 22 graphics primitives
            sage: GP.set_edges(edge_color='black')
            sage: GP.plot()
            Graphics object consisting of 22 graphics primitives

            sage: d = DiGraph({}, loops=True, multiedges=True, sparse=True)
            sage: d.add_edges([(0,0,'a'),(0,0,'b'),(0,1,'c'),(0,1,'d'),
            ...     (0,1,'e'),(0,1,'f'),(0,1,'f'),(2,1,'g'),(2,2,'h')])
            sage: GP = d.graphplot(vertex_size=100, edge_labels=True, color_by_label=True, edge_style='dashed')
            sage: GP.set_edges(edge_style='solid')
            sage: GP.plot()
            Graphics object consisting of 24 graphics primitives
            sage: GP.set_edges(edge_color='black')
            sage: GP.plot()
            Graphics object consisting of 24 graphics primitives

        TESTS::

            sage: G = Graph("Fooba")
            sage: G.show(edge_colors={'red':[(3,6),(2,5)]})

        Verify that default edge labels are pretty close to being between the vertices
        in some cases where they weren't due to truncating division (:trac:`10124`)::

            sage: test_graphs = graphs.FruchtGraph(), graphs.BullGraph()
            sage: tol = 0.001
            sage: for G in test_graphs:
            ...       E=G.edges()
            ...       for e0, e1, elab in E:
            ...           G.set_edge_label(e0, e1, '%d %d' % (e0, e1))
            ...       gp = G.graphplot(save_pos=True,edge_labels=True)
            ...       vx = gp._plot_components['vertices'][0].xdata
            ...       vy = gp._plot_components['vertices'][0].ydata
            ...       for elab in gp._plot_components['edge_labels']:
            ...           textobj = elab[0]
            ...           x, y, s = textobj.x, textobj.y, textobj.string
            ...           v0, v1 = map(int, s.split())
            ...           vn = vector(((x-(vx[v0]+vx[v1])/2.),y-(vy[v0]+vy[v1])/2.)).norm()
            ...           assert vn < tol

        """
        for arg in edge_options:
            self._options[arg] = edge_options[arg]
        if 'edge_colors' in edge_options: self._options['color_by_label'] = False

        # Handle base edge options: thickness, linestyle
        eoptions={}
        if 'edge_style' in self._options:
            from sage.plot.misc import get_matplotlib_linestyle
            eoptions['linestyle'] = get_matplotlib_linestyle(
                                        self._options['edge_style'],
                                        return_type='long')
        if 'thickness' in self._options:
            eoptions['thickness'] = self._options['thickness']

        # Set labels param to add labels on the fly
        labels = False
        if self._options['edge_labels']:
            labels = True
            self._plot_components['edge_labels'] = []

        # Make dict collection of all edges (keep label and edge color)
        edges_to_draw = {}
        if self._options['color_by_label'] or isinstance(self._options['edge_colors'], dict):
            if self._options['color_by_label']:
                edge_colors = self._graph._color_by_label(format=self._options['color_by_label'])
            else: edge_colors = self._options['edge_colors']
            for color in edge_colors:
                for edge in edge_colors[color]:
                    key = tuple(sorted([edge[0],edge[1]]))
                    if key == (edge[0],edge[1]): head = 1
                    else: head = 0

                    if len(edge) < 3:
                        label = self._graph.edge_label(edge[0],edge[1])
                        if isinstance(label, list):
                            if key in edges_to_draw:
                                edges_to_draw[key].append((label[-1], color, head))
                            else:
                                edges_to_draw[key] = [(label[-1], color, head)]
                            for i in range(len(label)-1):
                                edges_to_draw[key].append((label[-1], color, head))
                    else:
                        label = edge[2]

                    if key in edges_to_draw:
                        edges_to_draw[key].append((label, color, head))
                    else:
                        edges_to_draw[key] = [(label, color, head)]
            # add unspecified edges in (default color black)
            for edge in self._graph.edge_iterator():
                key = tuple(sorted([edge[0],edge[1]]))
                label = edge[2]
                specified = False
                if key in edges_to_draw:
                    for old_label, old_color, old_head in edges_to_draw[key]:
                        if label == old_label:
                            specified = True
                            break
                if not specified:
                    if key == (edge[0],edge[1]): head = 1
                    else: head = 0
                    edges_to_draw[key] = [(label, 'black', head)]
        else:
            for edge in self._graph.edges(sort=True):
                key = tuple(sorted([edge[0],edge[1]]))
                if key == (edge[0],edge[1]): head = 1
                else: head = 0
                if key in edges_to_draw:
                    edges_to_draw[key].append((edge[2], self._options['edge_color'], head))
                else:
                    edges_to_draw[key] = [(edge[2], self._options['edge_color'], head)]

        if edges_to_draw:
            self._plot_components['edges'] = []
        else:
            return

        # Check for multi-edges or loops
        if self._arcs or self._loops:
            tmp = edges_to_draw.copy()
            dist = self._options['dist']*2.
            loop_size = self._options['loop_size']
            max_dist = self._options['max_dist']
            from sage.functions.all import sqrt
            for (a,b) in tmp:
                if a == b:
                    # Loops
                    distance = dist
                    local_labels = edges_to_draw.pop((a,b))
                    if len(local_labels)*dist > max_dist:
                        distance = float(max_dist)/len(local_labels)
                    curr_loop_size = loop_size
                    for i in range(len(local_labels)):
                        self._plot_components['edges'].append(circle((self._pos[a][0],self._pos[a][1]-curr_loop_size), curr_loop_size, rgbcolor=local_labels[i][1], **eoptions))
                        if labels:
                            self._plot_components['edge_labels'].append(text(local_labels[i][0], (self._pos[a][0], self._pos[a][1]-2*curr_loop_size)))
                        curr_loop_size += distance/4
                elif len(edges_to_draw[(a,b)]) > 1:
                    # Multi-edge
                    local_labels = edges_to_draw.pop((a,b))

                    # Compute perpendicular bisector
                    p1 = self._pos[a]
                    p2 = self._pos[b]
                    M = ((p1[0]+p2[0])/2., (p1[1]+p2[1])/2.) # midpoint
                    if not p1[1] == p2[1]:
                        S = float(p1[0]-p2[0])/(p2[1]-p1[1]) # perp slope
                        y = lambda x : S*x-S*M[0]+M[1] # perp bisector line

                        # f,g are functions of distance d to determine x values
                        # on line y at d from point M
                        f = lambda d : sqrt(d**2/(1.+S**2)) + M[0]
                        g = lambda d : -sqrt(d**2/(1.+S**2)) + M[0]

                        odd_x = f
                        even_x = g
                        if p1[0] == p2[0]:
                            odd_y = lambda d : M[1]
                            even_y = odd_y
                        else:
                            odd_y = lambda x : y(f(x))
                            even_y = lambda x : y(g(x))
                    else:
                        odd_x = lambda d : M[0]
                        even_x = odd_x
                        odd_y = lambda d : M[1] + d
                        even_y = lambda d : M[1] - d

                    # We now have the control points for each bezier curve
                    # in terms of distance parameter d.
                    # Also note that the label for each edge should be drawn at d/2.
                    # (This is because we're using the perp bisectors).
                    distance = dist
                    if len(local_labels)*dist > max_dist:
                        distance = float(max_dist)/len(local_labels)
                    for i in range(len(local_labels)//2):
                        k = (i+1.0)*distance
                        if self._arcdigraph:
                            odd_start = self._polar_hack_for_multidigraph(p1, [odd_x(k),odd_y(k)], self._vertex_radius)[0]
                            odd_end = self._polar_hack_for_multidigraph([odd_x(k),odd_y(k)], p2, self._vertex_radius)[1]
                            even_start = self._polar_hack_for_multidigraph(p1, [even_x(k),even_y(k)], self._vertex_radius)[0]
                            even_end = self._polar_hack_for_multidigraph([even_x(k),even_y(k)], p2, self._vertex_radius)[1]
                            self._plot_components['edges'].append(arrow(path=[[odd_start,[odd_x(k),odd_y(k)],odd_end]], head=local_labels[2*i][2], zorder=1, rgbcolor=local_labels[2*i][1], **eoptions))
                            self._plot_components['edges'].append(arrow(path=[[even_start,[even_x(k),even_y(k)],even_end]], head=local_labels[2*i+1][2], zorder=1, rgbcolor=local_labels[2*i+1][1], **eoptions))
                        else:
                            self._plot_components['edges'].append(bezier_path([[p1,[odd_x(k),odd_y(k)],p2]],zorder=1, rgbcolor=local_labels[2*i][1], **eoptions))
                            self._plot_components['edges'].append(bezier_path([[p1,[even_x(k),even_y(k)],p2]],zorder=1, rgbcolor=local_labels[2*i+1][1], **eoptions))
                        if labels:
                            j = k/2.0
                            self._plot_components['edge_labels'].append(text(local_labels[2*i][0],[odd_x(j),odd_y(j)]))
                            self._plot_components['edge_labels'].append(text(local_labels[2*i+1][0],[even_x(j),even_y(j)]))
                    if len(local_labels)%2 == 1:
                        edges_to_draw[(a,b)] = [local_labels[-1]] # draw line for last odd

        dir = self._graph.is_directed()
        for (a,b) in edges_to_draw:
            if self._arcdigraph:
                C,D = self._polar_hack_for_multidigraph(self._pos[a], self._pos[b], self._vertex_radius)
                self._plot_components['edges'].append(arrow(C,D, rgbcolor=edges_to_draw[(a,b)][0][1], head=edges_to_draw[(a,b)][0][2], **eoptions))
                if labels:
                    self._plot_components['edge_labels'].append(text(str(edges_to_draw[(a,b)][0][0]),[(C[0]+D[0])/2., (C[1]+D[1])/2.]))
            elif dir:
                self._plot_components['edges'].append(arrow(self._pos[a],self._pos[b], rgbcolor=edges_to_draw[(a,b)][0][1], arrowshorten=self._arrowshorten, head=edges_to_draw[(a,b)][0][2], **eoptions))
            else:
                self._plot_components['edges'].append(line([self._pos[a],self._pos[b]], rgbcolor=edges_to_draw[(a,b)][0][1], **eoptions))
            if labels and not self._arcdigraph:
                self._plot_components['edge_labels'].append(text(str(edges_to_draw[(a,b)][0][0]),[(self._pos[a][0]+self._pos[b][0])/2., (self._pos[a][1]+self._pos[b][1])/2.]))
Exemplo n.º 25
0
    def _render_on_subplot(self, subplot):
        r"""
        Render this arrow in a subplot.  This is the key function that
        defines how this arrow graphics primitive is rendered in
        matplotlib's library.

        EXAMPLES:

        This function implicitly ends up rendering this arrow on
        a matplotlib subplot::

            sage: arrow((0,1), (2,-1))
            Graphics object consisting of 1 graphics primitive

        TESTS:

        The length of the ends (shrinkA and shrinkB) should not depend
        on the width of the arrow, because Matplotlib already takes
        this into account. See :trac:`12836`::

            sage: fig = Graphics().matplotlib()
            sage: sp = fig.add_subplot(1,1,1, label='axis1')
            sage: a = arrow((0,0), (1,1))
            sage: b = arrow((0,0), (1,1), width=20)
            sage: p1 = a[0]._render_on_subplot(sp)
            sage: p2 = b[0]._render_on_subplot(sp)
            sage: p1.shrinkA == p2.shrinkA
            True
            sage: p1.shrinkB == p2.shrinkB
            True

        Dashed arrows should have solid arrowheads, :trac:`12852`. We tried to
        make up a test for this, which turned out to be fragile and hence was
        removed. In general, robust testing of graphics seems basically need a
        human eye or AI.
        """
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        head = options.pop('head')
        if head == 0: style = '<|-'
        elif head == 1: style = '-|>'
        elif head == 2: style = '<|-|>'
        else:
            raise KeyError(
                'head parameter must be one of 0 (start), 1 (end) or 2 (both).'
            )
        width = float(options['width'])
        arrowshorten_end = float(options.get('arrowshorten', 0)) / 2.0
        arrowsize = float(options.get('arrowsize', 5))
        head_width = arrowsize
        head_length = arrowsize * 2.0
        color = to_mpl_color(options['rgbcolor'])
        from matplotlib.patches import FancyArrowPatch
        p = FancyArrowPatch(
            (self.xtail, self.ytail), (self.xhead, self.yhead),
            lw=width,
            arrowstyle='%s,head_width=%s,head_length=%s' %
            (style, head_width, head_length),
            shrinkA=arrowshorten_end,
            shrinkB=arrowshorten_end,
            fc=color,
            ec=color,
            linestyle=get_matplotlib_linestyle(options['linestyle'],
                                               return_type='long'))
        p.set_zorder(options['zorder'])
        p.set_label(options['legend_label'])

        if options['linestyle'] != 'solid':
            # The next few lines work around a design issue in matplotlib.
            # Currently, the specified linestyle is used to draw both the path
            # and the arrowhead.  If linestyle is 'dashed', this looks really
            # odd. This code is from Jae-Joon Lee in response to a post to the
            # matplotlib mailing list.
            # See http://sourceforge.net/mailarchive/forum.php?thread_name=CAG%3DuJ%2Bnw2dE05P9TOXTz_zp-mGP3cY801vMH7yt6vgP9_WzU8w%40mail.gmail.com&forum_name=matplotlib-users

            import matplotlib.patheffects as pe

            class CheckNthSubPath(object):
                def __init__(self, patch, n):
                    """
                    creates an callable object that returns True if the
                    provided path is the n-th path from the patch.
                    """
                    self._patch = patch
                    self._n = n

                def get_paths(self, renderer):
                    self._patch.set_dpi_cor(renderer.points_to_pixels(1.))
                    paths, fillables = self._patch.get_path_in_displaycoord()
                    return paths

                def __call__(self, renderer, gc, tpath, affine, rgbFace):
                    path = self.get_paths(renderer)[self._n]
                    vert1, code1 = path.vertices, path.codes
                    import numpy as np

                    return np.array_equal(vert1,
                                          tpath.vertices) and np.array_equal(
                                              code1, tpath.codes)

            class ConditionalStroke(pe.RendererBase):
                def __init__(self, condition_func, pe_list):
                    """
                    path effect that is only applied when the condition_func
                    returns True.
                    """
                    super(ConditionalStroke, self).__init__()
                    self._pe_list = pe_list
                    self._condition_func = condition_func

                def draw_path(self, renderer, gc, tpath, affine, rgbFace):

                    if self._condition_func(renderer, gc, tpath, affine,
                                            rgbFace):
                        for pe1 in self._pe_list:
                            pe1.draw_path(renderer, gc, tpath, affine, rgbFace)

            pe1 = ConditionalStroke(CheckNthSubPath(p, 0), [pe.Stroke()])
            pe2 = ConditionalStroke(
                CheckNthSubPath(p, 1),
                [pe.Stroke(dashes={
                    'dash_offset': 0,
                    'dash_list': None
                })])
            p.set_path_effects([pe1, pe2])

        subplot.add_patch(p)
        return p
Exemplo n.º 26
0
    def _render_on_subplot(self, subplot):
        r"""
        Render this arrow in a subplot.  This is the key function that
        defines how this arrow graphics primitive is rendered in
        matplotlib's library.

        EXAMPLES:

        This function implicitly ends up rendering this arrow on
        a matplotlib subplot::

            sage: arrow((0,1), (2,-1))

        TESTS:

        The length of the ends (shrinkA and shrinkB) should not depend
        on the width of the arrow, because Matplotlib already takes
        this into account. See :trac:`12836`::

            sage: fig = Graphics().matplotlib()
            sage: sp = fig.add_subplot(1,1,1)
            sage: a = arrow((0,0), (1,1))
            sage: b = arrow((0,0), (1,1), width=20)
            sage: p1 = a[0]._render_on_subplot(sp)
            sage: p2 = b[0]._render_on_subplot(sp)
            sage: p1.shrinkA == p2.shrinkA
            True
            sage: p1.shrinkB == p2.shrinkB
            True

        Dashed arrows should have solid arrowheads,
        :trac:`12852`. This test saves the plot of a dashed arrow to
        an EPS file. Within the EPS file, ``stroke`` will be called
        twice: once to draw the line, and again to draw the
        arrowhead. We check that both calls do not occur while the
        dashed line style is enabled::

            sage: a = arrow((0,0), (1,1), linestyle='dashed')
            sage: filename = tmp_filename(ext='.eps')
            sage: a.save(filename=filename)
            sage: with open(filename, 'r') as f:
            ....:     contents = f.read().replace('\n', ' ')
            sage: two_stroke_pattern = r'setdash.*stroke.*stroke.*setdash'
            sage: import re
            sage: two_stroke_re = re.compile(two_stroke_pattern)
            sage: two_stroke_re.search(contents) is None
            True
        """
        from sage.plot.misc import get_matplotlib_linestyle

        options = self.options()
        head = options.pop("head")
        if head == 0:
            style = "<|-"
        elif head == 1:
            style = "-|>"
        elif head == 2:
            style = "<|-|>"
        else:
            raise KeyError("head parameter must be one of 0 (start), 1 (end) or 2 (both).")
        width = float(options["width"])
        arrowshorten_end = float(options.get("arrowshorten", 0)) / 2.0
        arrowsize = float(options.get("arrowsize", 5))
        head_width = arrowsize
        head_length = arrowsize * 2.0
        color = to_mpl_color(options["rgbcolor"])
        from matplotlib.patches import FancyArrowPatch

        p = FancyArrowPatch(
            (self.xtail, self.ytail),
            (self.xhead, self.yhead),
            lw=width,
            arrowstyle="%s,head_width=%s,head_length=%s" % (style, head_width, head_length),
            shrinkA=arrowshorten_end,
            shrinkB=arrowshorten_end,
            fc=color,
            ec=color,
        )
        p.set_linestyle(get_matplotlib_linestyle(options["linestyle"], return_type="long"))
        p.set_zorder(options["zorder"])
        p.set_label(options["legend_label"])

        if options["linestyle"] != "solid":
            # The next few lines work around a design issue in matplotlib. Currently, the specified
            # linestyle is used to draw both the path and the arrowhead.  If linestyle is 'dashed', this
            # looks really odd.  This code is from Jae-Joon Lee in response to a post to the matplotlib mailing
            # list.  See http://sourceforge.net/mailarchive/forum.php?thread_name=CAG%3DuJ%2Bnw2dE05P9TOXTz_zp-mGP3cY801vMH7yt6vgP9_WzU8w%40mail.gmail.com&forum_name=matplotlib-users

            import matplotlib.patheffects as pe

            class CheckNthSubPath(object):
                def __init__(self, patch, n):
                    """
                    creates an callable object that returns True if the provided
                    path is the n-th path from the patch.
                    """
                    self._patch = patch
                    self._n = n

                def get_paths(self, renderer):
                    self._patch.set_dpi_cor(renderer.points_to_pixels(1.0))
                    paths, fillables = self._patch.get_path_in_displaycoord()
                    return paths

                def __call__(self, renderer, gc, tpath, affine, rgbFace):
                    path = self.get_paths(renderer)[self._n]
                    vert1, code1 = path.vertices, path.codes
                    import numpy as np

                    if np.all(vert1 == tpath.vertices) and np.all(code1 == tpath.codes):
                        return True
                    else:
                        return False

            class ConditionalStroke(pe._Base):
                def __init__(self, condition_func, pe_list):
                    """
                    path effect that is only applied when the condition_func
                    returns True.
                    """
                    super(ConditionalStroke, self).__init__()
                    self._pe_list = pe_list
                    self._condition_func = condition_func

                def draw_path(self, renderer, gc, tpath, affine, rgbFace):

                    if self._condition_func(renderer, gc, tpath, affine, rgbFace):
                        for pe1 in self._pe_list:
                            pe1.draw_path(renderer, gc, tpath, affine, rgbFace)

            pe1 = ConditionalStroke(CheckNthSubPath(p, 0), [pe.Stroke()])
            pe2 = ConditionalStroke(CheckNthSubPath(p, 1), [pe.Stroke(linestyle="solid")])
            p.set_path_effects([pe1, pe2])

        subplot.add_patch(p)
        return p