Esempio n. 1
0
def bar_chart(datalist, **options):
    """
    A bar chart of (currently) one list of numerical data.
    Support for more data lists in progress.

    EXAMPLES:

    A bar_chart with blue bars::

        sage: bar_chart([1,2,3,4])

    A bar_chart with thinner bars::

        sage: bar_chart([x^2 for x in range(1,20)], width=0.2)

    A bar_chart with negative values and red bars::

        sage: bar_chart([-3,5,-6,11], rgbcolor=(1,0,0))

    A bar chart with a legend (it's possible, not necessarily useful)::

        sage: bar_chart([-1,1,-1,1], legend_label='wave')

    Extra options will get passed on to show(), as long as they are valid::

        sage: bar_chart([-2,8,-7,3], rgbcolor=(1,0,0), axes=False)
        sage: bar_chart([-2,8,-7,3], rgbcolor=(1,0,0)).show(axes=False) # These are equivalent
    """
    dl = len(datalist)
    #if dl > 1:
    #    print "WARNING, currently only 1 data set allowed"
    #    datalist = datalist[0]
    if dl == 3:
        datalist = datalist + [0]
    #bardata = []
    #cnt = 1
    #for pnts in datalist:
    #ind = [i+cnt/dl for i in range(len(pnts))]
    #bardata.append([ind, pnts, xrange, yrange])
    #cnt += 1

    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    #TODO: improve below for multiple data sets!
    #cnt = 1
    #for ind, pnts, xrange, yrange in bardata:
    #options={'rgbcolor':hue(cnt/dl),'width':0.5/dl}
    #    g._bar_chart(ind, pnts, xrange, yrange, options=options)
    #    cnt += 1
    #else:
    ind = range(len(datalist))
    g.add_primitive(BarChart(ind, datalist, options=options))
    if options['legend_label']:
        g.legend(True)
    return g
Esempio n. 2
0
    def plot_function(self, **d):
        r"""
        Return a plot of the interval exchange transformation as a
        function.

        INPUT:

        - Any option that is accepted by line2d

        OUTPUT:

        2d plot -- a plot of the iet as a function

        EXAMPLES::

            sage: from surface_dynamics.all import *

            sage: t = iet.IntervalExchangeTransformation(('a b c d','d a c b'),[1,1,1,1])
            sage: t.plot_function(rgbcolor=(0,1,0))    # not tested (problem with matplotlib font cache)
            Graphics object consisting of 4 graphics primitives
        """
        from sage.plot.plot import Graphics
        from sage.plot.plot import line2d

        G = Graphics()
        l = self.singularities()
        t = self._permutation._twin

        for i in range(len(self._permutation)):
            j = t[0][i]
            G += line2d([(l[0][i], l[1][j]), (l[0][i + 1], l[1][j + 1])], **d)

        return G
Esempio n. 3
0
    def plot_function(self,**d):
        r"""
        Return a plot of the interval exchange transformation as a
        function.

        INPUT:

        - Any option that is accepted by line2d

        OUTPUT:

        2d plot -- a plot of the iet as a function

        EXAMPLES::

            sage: t = iet.IntervalExchangeTransformation(('a b c d','d a c b'),[1,1,1,1])
            sage: t.plot_function(rgbcolor=(0,1,0))
        """
        from sage.plot.plot import Graphics
        from sage.plot.plot import line2d

        G = Graphics()
        l = self.singularities()
        t = self._permutation._twin

        for i in range(len(self._permutation)):
            j = t[0][i]
            G += line2d([(l[0][i],l[1][j]),(l[0][i+1],l[1][j+1])],**d)

        return G
Esempio n. 4
0
    def plot(self, model='UHP'):
        r"""
        Plot the frieze as an ideal hyperbolic polygon.

        This is only defined up to isometry of the hyperbolic plane.

        We are identifying the boundary of the hyperbolic plane with the
        real projective line.

        The option ``model`` must be one of

        * ``'UHP'`` - (default) for the upper half plane model
        * ``'PD'`` - for the Poincare disk model
        * ``'KM'`` - for the Klein model

        The hyperboloid model is not an option as this does not implement
        boundary points.

        .. PLOT::
            :width: 400 px

            t = path_tableaux.FriezePattern([1,2,7,5,3,7,4,1])
            sphinx_plot(t.plot())

        EXAMPLES::

            sage: t = path_tableaux.FriezePattern([1,2,7,5,3,7,4,1])
            sage: t.plot()
            Graphics object consisting of 18 graphics primitives

            sage: t.plot(model='UHP')
            Graphics object consisting of 18 graphics primitives

            sage: t.plot(model='PD')
            Traceback (most recent call last):
            ...
            TypeError: '>' not supported between instances of 'NotANumber' and 'Pi'
            sage: t.plot(model='KM')
            Graphics object consisting of 18 graphics primitives
        """
        from sage.geometry.hyperbolic_space.hyperbolic_interface import HyperbolicPlane
        from sage.plot.plot import Graphics
        models = {
            'UHP': HyperbolicPlane().UHP(),
            'PD': HyperbolicPlane().PD(),
            'KM': HyperbolicPlane().KM(),
        }
        if model not in models:
            raise ValueError(f"{model} must be one of ``UHP``, ``PD``, ``KM``")
        M = models[model]

        U = HyperbolicPlane().UHP()
        cd = CylindricalDiagram(self).diagram
        num = cd[0][:-1]
        den = cd[1][2:]
        vt = [M(U.get_point(x / (x + y))) for x, y in zip(num, den)]
        gd = [M.get_geodesic(vt[i - 1], vt[i]) for i in range(len(vt))]
        return sum([a.plot() for a in gd], Graphics()).plot()
Esempio n. 5
0
def bar_chart(datalist, **options):
    """
    A bar chart of (currently) one list of numerical data.
    Support for more data lists in progress.

    EXAMPLES:

    A bar_chart with blue bars::

        sage: bar_chart([1,2,3,4])

    A bar_chart with thinner bars::

        sage: bar_chart([x^2 for x in range(1,20)], width=0.2)

    A bar_chart with negative values and red bars::

        sage: bar_chart([-3,5,-6,11], rgbcolor=(1,0,0))

    A bar chart with a legend (it's possible, not necessarily useful)::

        sage: bar_chart([-1,1,-1,1], legend_label='wave')

    Extra options will get passed on to show(), as long as they are valid::

        sage: bar_chart([-2,8,-7,3], rgbcolor=(1,0,0), axes=False)
        sage: bar_chart([-2,8,-7,3], rgbcolor=(1,0,0)).show(axes=False) # These are equivalent
    """
    dl = len(datalist)
    #if dl > 1:
    #    print "WARNING, currently only 1 data set allowed"
    #    datalist = datalist[0]
    if dl == 3:
        datalist = datalist+[0]
    #bardata = []
    #cnt = 1
    #for pnts in datalist:
        #ind = [i+cnt/dl for i in range(len(pnts))]
        #bardata.append([ind, pnts, xrange, yrange])
        #cnt += 1

    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    #TODO: improve below for multiple data sets!
    #cnt = 1
    #for ind, pnts, xrange, yrange in bardata:
        #options={'rgbcolor':hue(cnt/dl),'width':0.5/dl}
    #    g._bar_chart(ind, pnts, xrange, yrange, options=options)
    #    cnt += 1
    #else:
    ind = range(len(datalist))
    g.add_primitive(BarChart(ind, datalist, options=options))
    if options['legend_label']:
        g.legend(True)
    return g
Esempio n. 6
0
def show_pentaminos(box=(5, 8, 2)):
    r"""
    Show the 17 3-D pentaminos included in the game and the `5 \times 8
    \times 2` box where 16 of them must fit.

    INPUT:

    - ``box`` - tuple of size three (optional, default: ``(5,8,2)``),
      size of the box

    OUTPUT:

        3D Graphic object

    EXAMPLES::

        sage: from sage.games.quantumino import show_pentaminos
        sage: show_pentaminos()    # not tested (1s)

    To remove the frame do::

        sage: show_pentaminos().show(frame=False)  # not tested (1s)
    """
    G = Graphics()
    for i, p in enumerate(pentaminos):
        x = 3.5 * (i % 4)
        y = 3.5 * (i / 4)
        q = p + (x, y, 0)
        G += q.show3d()
        G += text3d(str(i), (x, y, 2))
    G += cube(color='gray', opacity=0.5).scale(box).translate((17, 6, 0))

    # hack to set the aspect ratio to 1
    a, b = G.bounding_box()
    a, b = map(vector, (a, b))
    G.frame_aspect_ratio(tuple(b - a))

    return G
Esempio n. 7
0
def show_pentaminos(box=(5, 8, 2)):
    r"""
    Show the 17 3-D pentaminos included in the game and the `5 \times 8
    \times 2` box where 16 of them must fit.

    INPUT:

    - ``box`` - tuple of size three (optional, default: ``(5,8,2)``),
      size of the box

    OUTPUT:

        3D Graphic object

    EXAMPLES::

        sage: from sage.games.quantumino import show_pentaminos
        sage: show_pentaminos()    # not tested (1s)

    To remove the frame do::

        sage: show_pentaminos().show(frame=False)  # not tested (1s)
    """
    G = Graphics()
    for i, p in enumerate(pentaminos):
        x = 3.5 * (i % 4)
        y = 3.5 * (i / 4)
        q = p + (x, y, 0)
        G += q.show3d()
        G += text3d(str(i), (x, y, 2))
    G += cube(color="gray", opacity=0.5).scale(box).translate((17, 6, 0))

    # hack to set the aspect ratio to 1
    a, b = G.bounding_box()
    a, b = map(vector, (a, b))
    G.frame_aspect_ratio(tuple(b - a))

    return G
Esempio n. 8
0
    def show3d(self, size=0.85):
        r"""
        Return the solution as a 3D Graphic object.

        OUTPUT:

            3D Graphic Object

        EXAMPLES::

            sage: from sage.games.quantumino import QuantuminoSolver
            sage: s = QuantuminoSolver(0).solve().next()    # not tested (1.5s)
            sage: G = s.show3d()                            # not tested (<1s)
            sage: type(G)                                   # not tested
            <class 'sage.plot.plot3d.base.Graphics3dGroup'>

        To remove the frame::

            sage: G.show(frame=False) # not tested

        To see the solution with Tachyon viewer::

            sage: G.show(viewer='tachyon', frame=False) # not tested
        """
        G = Graphics()
        for p in self:
            G += p.show3d(size=size)
        aside_pento = self._aside.canonical() + (2.5 * size / 0.75,
                                                 -4 * size / 0.75, 0)
        G += aside_pento.show3d(size=size)

        # hack to set the aspect ratio to 1
        a, b = G.bounding_box()
        a, b = map(vector, (a, b))
        G.frame_aspect_ratio(tuple(b - a))

        return G
Esempio n. 9
0
def scatter_plot(datalist, **options):
    """
    Returns a Graphics object of a scatter plot containing all points in 
    the datalist.  Type ``scatter_plot.options`` to see all available
    plotting options.
    
    INPUT:

    - ``datalist`` -- a list of tuples ``(x,y)``

    - ``alpha`` -- default: 1

    - ``markersize`` -- default: 50

    - ``marker``  - The style of the markers (default ``"o"``), which is one of
       - ``"None"`` or ``" "`` or ``""`` (nothing)
       - ``","`` (pixel), ``"."`` (point)
       - ``"_"`` (horizontal line), ``"|"`` (vertical line)
       - ``"o"`` (circle), ``"p"`` (pentagon), ``"s"`` (square), ``"x"`` (x), ``"+"`` (plus), ``"*"`` (star)
       - ``"D"`` (diamond), ``"d"`` (thin diamond)
       - ``"H"`` (hexagon), ``"h"`` (alternative hexagon)
       - ``"<"`` (triangle left), ``">"`` (triangle right), ``"^"`` (triangle up), ``"v"`` (triangle down)
       - ``"1"`` (tri down), ``"2"`` (tri up), ``"3"`` (tri left), ``"4"`` (tri right)
       - ``0`` (tick left), ``1`` (tick right), ``2`` (tick up), ``3`` (tick down)
       - ``4`` (caret left), ``5`` (caret right), ``6`` (caret up), ``7`` (caret down)
       - ``"$...$"`` (math TeX string)

    - ``facecolor`` -- default: ``'#fec7b8'``

    - ``edgecolor`` -- default: ``'black'``

    - ``zorder`` -- default: 5
        
    EXAMPLES::

        sage: scatter_plot([[0,1],[2,2],[4.3,1.1]], marker='s')
        
    Extra options will get passed on to :meth:`~sage.plot.plot.Graphics.show`, as long as they are valid::

        sage: scatter_plot([(0, 0), (1, 1)], markersize=100, facecolor='green', ymax=100)
        sage: scatter_plot([(0, 0), (1, 1)], markersize=100, facecolor='green').show(ymax=100) # These are equivalent
    """
    import numpy
    from sage.plot.plot import Graphics
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    data = numpy.array(datalist, dtype='float')
    if len(data) != 0:
        xdata = data[:, 0]
        ydata = data[:, 1]
        g.add_primitive(ScatterPlot(xdata, ydata, options=options))
    return g
Esempio n. 10
0
    def show3d(self, size=0.85):
        r"""
        Return the solution as a 3D Graphic object.

        OUTPUT:

            3D Graphic Object

        EXAMPLES::

            sage: from sage.games.quantumino import QuantuminoSolver
            sage: s = QuantuminoSolver(0).solve().next()    # not tested (1.5s)
            sage: G = s.show3d()                            # not tested (<1s)
            sage: type(G)                                   # not tested
            <class 'sage.plot.plot3d.base.Graphics3dGroup'>

        To remove the frame::

            sage: G.show(frame=False) # not tested

        To see the solution with Tachyon viewer::

            sage: G.show(viewer='tachyon', frame=False) # not tested
        """
        G = Graphics()
        for p in self:
            G += p.show3d(size=size)
        aside_pento = self._aside.canonical() + (2.5 * size / 0.75, -4 * size / 0.75, 0)
        G += aside_pento.show3d(size=size)

        # hack to set the aspect ratio to 1
        a, b = G.bounding_box()
        a, b = map(vector, (a, b))
        G.frame_aspect_ratio(tuple(b - a))

        return G
Esempio n. 11
0
def scatter_plot(datalist, **options):
    """
    Returns a Graphics object of a scatter plot containing all points in 
    the datalist.  Type ``scatter_plot.options`` to see all available
    plotting options.
    
    INPUT:

    - ``datalist`` -- a list of tuples ``(x,y)``

    - ``alpha`` -- default: 1

    - ``markersize`` -- default: 50

    - ``marker``  - The style of the markers (default ``"o"``), which is one of
       - ``"None"`` or ``" "`` or ``""`` (nothing)
       - ``","`` (pixel), ``"."`` (point)
       - ``"_"`` (horizontal line), ``"|"`` (vertical line)
       - ``"o"`` (circle), ``"p"`` (pentagon), ``"s"`` (square), ``"x"`` (x), ``"+"`` (plus), ``"*"`` (star)
       - ``"D"`` (diamond), ``"d"`` (thin diamond)
       - ``"H"`` (hexagon), ``"h"`` (alternative hexagon)
       - ``"<"`` (triangle left), ``">"`` (triangle right), ``"^"`` (triangle up), ``"v"`` (triangle down)
       - ``"1"`` (tri down), ``"2"`` (tri up), ``"3"`` (tri left), ``"4"`` (tri right)
       - ``0`` (tick left), ``1`` (tick right), ``2`` (tick up), ``3`` (tick down)
       - ``4`` (caret left), ``5`` (caret right), ``6`` (caret up), ``7`` (caret down)
       - ``"$...$"`` (math TeX string)

    - ``facecolor`` -- default: ``'#fec7b8'``

    - ``edgecolor`` -- default: ``'black'``

    - ``zorder`` -- default: 5
        
    EXAMPLES::

        sage: scatter_plot([[0,1],[2,2],[4.3,1.1]], marker='s')
        
    Extra options will get passed on to :meth:`~sage.plot.plot.Graphics.show`, as long as they are valid::

        sage: scatter_plot([(0, 0), (1, 1)], markersize=100, facecolor='green', ymax=100)
        sage: scatter_plot([(0, 0), (1, 1)], markersize=100, facecolor='green').show(ymax=100) # These are equivalent
    """
    import numpy
    from sage.plot.plot import Graphics
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    data = numpy.array(datalist, dtype='float')
    if len(data) != 0:
        xdata = data[:,0]
        ydata = data[:,1]
        g.add_primitive(ScatterPlot(xdata, ydata, options=options))
    return g
Esempio n. 12
0
    def triangulation(self):
        r"""
        Plot a regular polygon with some diagonals.

        If ``self`` is positive and integral then this will be a triangulation.

        .. PLOT::
            :width: 600 px

            G = path_tableaux.FriezePattern([1,2,7,5,3,7,4,1]).triangulation()
            p = graphics_array(G, 7, 6)
            sphinx_plot(p)

        EXAMPLES::

            sage: path_tableaux.FriezePattern([1,2,7,5,3,7,4,1]).triangulation()
            Graphics object consisting of 25 graphics primitives

            sage: path_tableaux.FriezePattern([1,2,1/7,5,3]).triangulation()
            Graphics object consisting of 12 graphics primitives

            sage: K.<sqrt2> = NumberField(x^2-2)
            sage: path_tableaux.FriezePattern([1,sqrt2,1,sqrt2,3,2*sqrt2,5,3*sqrt2,1], field=K).triangulation()
            Graphics object consisting of 24 graphics primitives
        """
        n = len(self) - 1
        cd = CylindricalDiagram(self).diagram
        from sage.plot.plot import Graphics
        from sage.plot.line import line
        from sage.plot.text import text
        from sage.functions.trig import sin, cos
        from sage.all import pi
        G = Graphics()
        G.set_aspect_ratio(1.0)

        vt = [(cos(2 * theta * pi / (n)), sin(2 * theta * pi / (n)))
              for theta in range(n + 1)]
        for i, p in enumerate(vt):
            G += text(str(i), [1.05 * p[0], 1.05 * p[1]])

        for i, r in enumerate(cd):
            for j, a in enumerate(r[:n]):
                if a == 1:
                    G += line([vt[i], vt[j]])

        G.axes(False)
        return G
Esempio n. 13
0
def _draw_funddom_d(coset_reps, format="MP", z0=I):
    r""" Draw a fundamental domain for self in the circle model
    INPUT:
    - ''format''  -- (default 'Disp') How to present the f.d.
    =  'S'  -- Display directly on the screen
    - z0          -- (default I) the upper-half plane is mapped to the disk by z-->(z-z0)/(z-z0.conjugate())
    EXAMPLES::


    sage: G=MySubgroup(Gamma0(3))
    sage: G._draw_funddom_d()

    """
    # The fundamental domain consists of copies of the standard fundamental domain
    pi = RR.pi()
    from sage.plot.plot import Graphics
    g = Graphics()
    bdcirc = _circ_arc(0, 2 * pi, 0, 1, 1000)
    g = g + bdcirc
    # Corners
    x1 = -RR(0.5)
    y1 = RR(sqrt(3) / 2)
    x2 = RR(0.5)
    y2 = RR(sqrt(3) / 2)
    l1 = _geodesic_between_two_points_d(x1, y1, x1, infinity)
    l2 = _geodesic_between_two_points_d(x2, y2, x2, infinity)
    c0 = _geodesic_between_two_points_d(x1, y1, x2, y2)
    tri = c0 + l1 + l2
    g = g + tri
    for A in coset_reps:
        [a, b, c, d] = A
        if (a == 1 and b == 0 and c == 0 and d == 1):
            continue
        if (a < 0):
            a = -a
            b = -b
            c = -c
            d = -1
        if (c == 0):  # then this is easier
            l1 = _geodesic_between_two_points_d(x1 + b, y1, x1 + b, infinity)
            l2 = _geodesic_between_two_points_d(x2 + b, y2, x2 + b, infinity)
            c0 = _geodesic_between_two_points_d(x1 + b, y1, x2 + b, y2)
            # c0=line(L0); l1=line(L1); l2=line(L2); l3=line(L3)
            tri = c0 + l1 + l2
            g = g + tri
        else:
            den = (c * x1 + d)**2 + c**2 * y1**2
            x1_t = (a * c * (x1**2 + y1**2) +
                    (a * d + b * c) * x1 + b * d) / den
            y1_t = y1 / den
            den = (c * x2 + d)**2 + c**2 * y2**2
            x2_t = (a * c * (x2**2 + y2**2) +
                    (a * d + b * c) * x2 + b * d) / den
            y2_t = y2 / den
            inf_t = a / c
            c0 = _geodesic_between_two_points_d(x1_t, y1_t, x2_t, y2_t)
            c1 = _geodesic_between_two_points_d(x1_t, y1_t, inf_t, 0.0)
            c2 = _geodesic_between_two_points_d(x2_t, y2_t, inf_t, 0.0)
            tri = c0 + c1 + c2
            g = g + tri
    g.xmax(1)
    g.ymax(1)
    g.xmin(-1)
    g.ymin(-1)
    g.set_aspect_ratio(1)
    return g
Esempio n. 14
0
def point2d(points, **options):
    r"""
    A point of size ``size`` defined by point = `(x,y)`.
    Point takes either a single tuple of coordinates or a list of tuples.

    Type ``point2d.options`` to see all options.

    EXAMPLES:

    A purple point from a single tuple or coordinates::

        sage: point((0.5, 0.5), rgbcolor=hue(0.75))
        
    Passing an empty list returns an empty plot::
        
        sage: point([])

    If you need a 2D point to live in 3-space later, 
    this is possible::

        sage: A=point((1,1))
        sage: a=A[0];a
        Point set defined by 1 point(s)
        sage: b=a.plot3d(z=3)

    This is also true with multiple points::

        sage: P=point([(0,0), (1,1)])
        sage: p=P[0]
        sage: q=p.plot3d(z=[2,3])

    Here are some random larger red points, given as a list of tuples::

        sage: point(((0.5, 0.5), (1, 2), (0.5, 0.9), (-1, -1)), rgbcolor=hue(1), size=30)

    And an example with a legend::

        sage: point((0,0), rgbcolor='black', pointsize=40, legend_label='origin')

    Extra options will get passed on to show(), as long as they are valid::

        sage: point([(cos(theta), sin(theta)) for theta in srange(0, 2*pi, pi/8)], frame=True)
        sage: point([(cos(theta), sin(theta)) for theta in srange(0, 2*pi, pi/8)]).show(frame=True) # These are equivalent

    Since Sage Version 4.4 (ticket #8599), the size of a 2d point can be
    given by the argument ``size`` instead of ``pointsize``. The argument
    ``pointsize`` is still supported::

        sage: point((3,4), size=100)

    ::

        sage: point((3,4), pointsize=100)
    """
    from sage.plot.plot import xydata_from_point_list, Graphics

    if points == []:
        return Graphics()
    xdata, ydata = xydata_from_point_list(points)
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(Point(xdata, ydata, options))
    if options["legend_label"]:
        g.legend(True)
    return g
Esempio n. 15
0
def histogram(datalist, **options):
    """
    Computes and draws the histogram for list(s) of numerical data.
    See examples for the many options; even more customization is
    available using matplotlib directly.

    INPUT:

    - ``datalist`` -- A list, or a list of lists, of numerical data
    - ``align`` -- (default: "mid") How the bars align inside of each bin.
      Acceptable values are "left", "right" or "mid"
    - ``alpha`` -- (float in [0,1], default: 1) The transparency of the plot
    - ``bins`` -- The number of sections in which to divide the range. Also
      can be a sequence of points within the range that create the
      partition
    - ``color`` -- The color of the face of the bars or list of colors if
      multiple data sets are given
    - ``cumulative`` -- (boolean - default: False) If True, then
      a histogram is computed in which each bin gives the counts in that
      bin plus all bins for smaller values.  Negative values give
      a reversed direction of accumulation
    - ``edgecolor`` -- The color of the border of each bar
    - ``fill`` -- (boolean - default: True) Whether to fill the bars
    - ``hatch`` -- (default: None) symbol to fill the bars with - one of
      "/", "\\", "|", "-", "+", "x", "o", "O", ".", "*", "" (or None)
    - ``hue`` -- The color of the bars given as a hue. See
      :mod:`~sage.plot.colors.hue` for more information on the hue
    - ``label`` -- A string label for each data list given
    - ``linewidth`` -- (float) width of the lines defining the bars
    - ``linestyle`` -- (default: 'solid') Style of the line. One of 'solid'
      or '-', 'dashed' or '--', 'dotted' or ':', 'dashdot' or '-.'
    - ``normed`` -- (boolean - default: False) If True, the counts are
      normalized to form a probability density.
    - ``range`` -- A list [min, max] which define the range of the
      histogram. Values outside of this range are treated as outliers and
      omitted from counts
    - ``rwidth`` -- (float in [0,1], default: 1) The relative width of the bars
      as a fraction of the bin width
    - ``stacked`` -- (boolean - default: False) If True, multiple data are
      stacked on top of each other
    - ``weights`` -- (list) A sequence of weights the same length as the data
      list. If supplied, then each value contributes its associated weight
      to the bin count
    - ``zorder`` -- (integer) the layer level at which to draw the histogram

    .. NOTE::

        The ``weights`` option works only with a single list. List of lists
        representing multiple data are not supported.

    EXAMPLES:

    A very basic histogram for four data points::

        sage: histogram([1,2,3,4], bins=2)
        Graphics object consisting of 1 graphics primitive

    We can see how the histogram compares to various distributions.
    Note the use of the ``normed`` keyword to guarantee the plot
    looks like the probability density function::

        sage: nv = normalvariate
        sage: H = histogram([nv(0,1) for _ in range(1000)], bins=20, normed=True, range=[-5,5])
        sage: P = plot( 1/sqrt(2*pi)*e^(-x^2/2), (x,-5,5), color='red', linestyle='--')
        sage: H+P
        Graphics object consisting of 2 graphics primitives

    There are many options one can use with histograms.  Some of these
    control the presentation of the data, even if it is boring::

        sage: histogram(list(range(100)), color=(1,0,0), label='mydata',\
              rwidth=.5, align="right")
        Graphics object consisting of 1 graphics primitive

    This includes many usual matplotlib styling options::

        sage: T = RealDistribution('lognormal', [0,1])
        sage: histogram( [T.get_random_element() for _ in range(100)], alpha=0.3,\
              edgecolor='red', fill=False, linestyle='dashed', hatch='O', linewidth=5)
        Graphics object consisting of 1 graphics primitive
        sage: histogram( [T.get_random_element() for _ in range(100)],linestyle='-.')
        Graphics object consisting of 1 graphics primitive

    We can do several data sets at once if desired::

        sage: histogram([srange(0,1,.1)*10, [nv(0, 1) for _ in range(100)]], color=['red','green'], bins=5)
        Graphics object consisting of 1 graphics primitive

    We have the option of stacking the data sets too::

        sage: histogram([ [1,1,1,1,2,2,2,3,3,3], [4,4,4,4,3,3,3,2,2,2] ], stacked=True, color=['blue', 'red'])
        Graphics object consisting of 1 graphics primitive

    It is possible to use weights with the histogram as well::

        sage: histogram(list(range(10)), bins=3, weights=[1,2,3,4,5,5,4,3,2,1])
        Graphics object consisting of 1 graphics primitive
    """
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(Histogram(datalist, options=options))
    return g
Esempio n. 16
0
    def plot(self, color='rainbow', orientation='bottom-top', gap=0.05, aspect_ratio=1, axes=False, **kwds):
        """
        Plot the braid

        The following options are available:

        - ``color`` -- (default: ``'rainbow'``) the color of the
          strands. Possible values are:

            * ``'rainbow'``, uses :meth:`~sage.plot.colors.rainbow`
              according to the number of strands.

            * a valid color name for :meth:`~sage.plot.bezier_path`
              and :meth:`~sage.plot.line`. Used for all strands.

            * a list or a tuple of colors for each individual strand.

        - ``orientation`` -- (default: ``'bottom-top'``) determines how
          the braid is printed. The possible values are:

            * ``'bottom-top'``, the braid is printed from bottom to top

            * ``'top-bottom'``, the braid is printed from top to bottom

            * ``'left-right'``, the braid is printed from left to right

        - ``gap`` -- floating point number (default: 0.05). determines
          the size of the gap left when a strand goes under another.

        - ``aspect_ratio`` -- floating point number (default:
          ``1``). The aspect ratio.

        - ``**kwds`` -- other keyword options that are passed to
          :meth:`~sage.plot.bezier_path` and :meth:`~sage.plot.line`.

        EXAMPLES::

            sage: B = BraidGroup(4, 's')
            sage: b = B([1, 2, 3, 1, 2, 1])
            sage: b.plot()
            sage: b.plot(color=["red", "blue", "red", "blue"])

            sage: B.<s,t> = BraidGroup(3)
            sage: b = t^-1*s^2
            sage: b.plot(orientation="left-right", color="red")
        """
        from sage.plot.bezier_path import bezier_path
        from sage.plot.plot import Graphics, line
        from sage.plot.colors import rainbow
        if orientation=='top-bottom':
            orx = 0
            ory = -1
            nx = 1
            ny = 0
        elif orientation=='left-right':
            orx = 1
            ory = 0
            nx = 0
            ny = -1
        elif orientation=='bottom-top':
            orx = 0
            ory = 1
            nx = 1
            ny = 0
        else:
            raise ValueError('unknown value for "orientation"')
        n = self.strands()
        if isinstance(color, (list, tuple)):
            if len(color) != n:
                raise TypeError("color (=%s) must contain exactly %d colors" % (color, n))
            col = list(color)
        elif color == "rainbow":
            col = rainbow(n)
        else:
            col = [color]*n
        braid = self.Tietze()
        a = Graphics()
        op = gap
        for i, m in enumerate(braid):
            for j in range(n):
                if m==j+1:
                    a += bezier_path([[(j*nx+i*orx, i*ory+j*ny), (j*nx+orx*(i+0.25), j*ny+ory*(i+0.25)),
                                       (nx*(j+0.5)+orx*(i+0.5), ny*(j+0.5)+ory*(i+0.5))],
                                      [(nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)),
                                       (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col[j], **kwds)
                elif m==j:
                    a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)),
                                       (nx*(j-0.5+4*op)+orx*(i+0.5-2*op), ny*(j-0.5+4*op)+ory*(i+0.5-2*op)),
                                       (nx*(j-0.5+2*op)+orx*(i+0.5-op), ny*(j-0.5+2*op)+ory*(i+0.5-op))]],
                                     color=col[j], **kwds)
                    a += bezier_path([[(nx*(j-0.5-2*op)+orx*(i+0.5+op), ny*(j-0.5-2*op)+ory*(i+0.5+op)),
                                       (nx*(j-0.5-4*op)+orx*(i+0.5+2*op), ny*(j-0.5-4*op)+ory*(i+0.5+2*op)),
                                       (nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)),
                                       (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col[j], **kwds)
                    col[j], col[j-1] = col[j-1], col[j]
                elif -m==j+1:
                    a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)),
                                       (nx*(j+0.5-4*op)+orx*(i+0.5-2*op), ny*(j+0.5-4*op)+ory*(i+0.5-2*op)),
                                       (nx*(j+0.5-2*op)+orx*(i+0.5-op), ny*(j+0.5-2*op)+ory*(i+0.5-op))]],
                                     color=col[j], **kwds)
                    a += bezier_path([[(nx*(j+0.5+2*op)+orx*(i+0.5+op), ny*(j+0.5+2*op)+ory*(i+0.5+op)),
                                       (nx*(j+0.5+4*op)+orx*(i+0.5+2*op), ny*(j+0.5+4*op)+ory*(i+0.5+2*op)),
                                       (nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)),
                                       (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col[j], **kwds)
                elif -m==j:
                    a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)),
                                       (nx*(j-0.5)+orx*(i+0.5), ny*(j-0.5)+ory*(i+0.5))],
                                      [(nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)),
                                       (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col[j], **kwds)
                    col[j], col[j-1] = col[j-1], col[j]
                else:
                    a += line([(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+1), ny*j+ory*(i+1))], color=col[j], **kwds)
        a.set_aspect_ratio(aspect_ratio)
        a.axes(axes)
        return a
Esempio n. 17
0
    def plot(self, color='blue', orientation='bottom-top', gap=0.05, aspect_ratio=1, axes=False, **kwds):
        """
        Plot the braid

        The following options are available:

        - ``orientation`` - (default: ``'bottom-top'``) determines how
          the braid is printed. The possible values are:

            * ``'bottom-top'``, the braid is printed from bottom to top

            * ``'top-bottom'``, the braid is printed from top to bottom

            * ``'left-right'``, the braid is printed from left to right

        - ``gap`` -- floating point number (default: 0.05). determines
          the size of the gap left when a strand goes under another.

        - ``aspect_ratio`` -- floating point number (default:
          ``1``). The aspect ratio.

        - ``**kwds`` -- other keyword options that are passed to
          :meth:`~sage.plot.bezier_path` and :meth:`~sage.plot.line`.

        EXAMPLES::

            sage: B = BraidGroup(4, 's')
            sage: b = B([1, 2, 3, 1, 2, 1])
            sage: b.plot()
        """
        from sage.plot.bezier_path import bezier_path
        from sage.plot.plot import Graphics, line
        if orientation=='top-bottom':
            orx = 0
            ory = -1
            nx = 1
            ny = 0
        elif orientation=='left-right':
            orx = 1
            ory = 0
            nx = 0
            ny = -1
        elif orientation=='bottom-top':
            orx = 0
            ory = 1
            nx = 1
            ny = 0
        else:
            raise ValueError('unknown value for "orientation"')
        col = color
        br = self.Tietze()
        n = self.strands()
        a = Graphics()
        op = gap
        for i in range(len(br)):
            m = br[i]
            for j in range(n):
                if m==j+1:
                    a += bezier_path([[(j*nx+i*orx, i*ory+j*ny), (j*nx+orx*(i+0.25), j*ny+ory*(i+0.25)),
                                       (nx*(j+0.5)+orx*(i+0.5), ny*(j+0.5)+ory*(i+0.5))],
                                      [(nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)),
                                       (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col, **kwds)
                elif m==j:
                    a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)),
                                       (nx*(j-0.5+4*op)+orx*(i+0.5-2*op), ny*(j-0.5+4*op)+ory*(i+0.5-2*op)),
                                       (nx*(j-0.5+2*op)+orx*(i+0.5-op), ny*(j-0.5+2*op)+ory*(i+0.5-op))]],
                                     color=col, **kwds)
                    a += bezier_path([[(nx*(j-0.5-2*op)+orx*(i+0.5+op), ny*(j-0.5-2*op)+ory*(i+0.5+op)),
                                       (nx*(j-0.5-4*op)+orx*(i+0.5+2*op), ny*(j-0.5-4*op)+ory*(i+0.5+2*op)),
                                       (nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)),
                                       (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col, **kwds)
                elif -m==j+1:
                    a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)),
                                       (nx*(j+0.5-4*op)+orx*(i+0.5-2*op), ny*(j+0.5-4*op)+ory*(i+0.5-2*op)),
                                       (nx*(j+0.5-2*op)+orx*(i+0.5-op), ny*(j+0.5-2*op)+ory*(i+0.5-op))]],
                                     color=col, **kwds)
                    a += bezier_path([[(nx*(j+0.5+2*op)+orx*(i+0.5+op), ny*(j+0.5+2*op)+ory*(i+0.5+op)),
                                       (nx*(j+0.5+4*op)+orx*(i+0.5+2*op), ny*(j+0.5+4*op)+ory*(i+0.5+2*op)),
                                       (nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)),
                                       (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col, **kwds)
                elif -m==j:
                    a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)),
                                       (nx*(j-0.5)+orx*(i+0.5), ny*(j-0.5)+ory*(i+0.5))],
                                      [(nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)),
                                       (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col, **kwds)
                else:
                    a += line([(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+1), ny*j+ory*(i+1))], color=col, **kwds)
        a.set_aspect_ratio(aspect_ratio)
        a.axes(axes)
        return a
Esempio n. 18
0
    def plot_towers(self, iterations, position=(0, 0), colors=None):
        """
        Plot the towers of this interval exchange obtained from Rauzy induction.

        INPUT:

        - ``nb_iterations`` -- the number of steps of Rauzy induction

        - ``colors`` -- (optional) colors for the towers

        EXAMPLES::

            sage: from surface_dynamics.all import *

            sage: p = iet.Permutation('A B', 'B A')
            sage: T = iet.IntervalExchangeTransformation(p, [0.41510826, 0.58489174])
            sage: T.plot_towers(iterations=5)   # not tested (problem with matplotlib font cache)
            Graphics object consisting of 65 graphics primitives
        """
        px, py = map(float, position)

        T, _, towers = self.rauzy_move(iterations=iterations, data=True)
        pi = T.permutation()
        A = pi.alphabet()
        lengths = map(float, T.lengths())

        if colors is None:
            from sage.plot.colors import rainbow
            colors = {a: z for a, z in zip(A, rainbow(len(A)))}

        from sage.plot.graphics import Graphics
        from sage.plot.line import line2d
        from sage.plot.polygon import polygon2d
        from sage.plot.text import text
        G = Graphics()
        x = px
        for letter in pi[0]:
            y = x + lengths[A.rank(letter)]
            tower = towers.image(letter)
            h = tower.length()
            G += line2d([(x, py), (x, py + h)], color='black')
            G += line2d([(y, py), (y, py + h)], color='black')
            for i, a in enumerate(tower):
                G += line2d([(x, py + i), (y, py + i)], color='black')
                G += polygon2d([(x, py + i), (y, py + i), (y, py + i + 1),
                                (x, py + i + 1)],
                               color=colors[a],
                               alpha=0.4)
                G += text(a, ((x + y) / 2, py + i + .5), color='darkgray')
            G += line2d([(x, py + h), (y, py + h)],
                        color='black',
                        linestyle='dashed')
            G += text(letter, ((x + y) / 2, py + h + .5),
                      color='black',
                      fontsize='large')
            x = y
        x = px
        G += line2d([(px, py - .5), (px + sum(lengths), py - .5)],
                    color='black')
        for letter in pi[1]:
            y = x + lengths[A.rank(letter)]
            G += line2d([(x, py - .7), (x, py - .3)], color='black')
            G += text(letter, ((x + y) / 2, py - .5),
                      color='black',
                      fontsize='large')
            x = y
        G += line2d([(x, py - .7), (x, py - .3)], color='black')

        return G
Esempio n. 19
0
def ellipse(center, r1, r2, angle=0, **options):
    """
    Return an ellipse centered at a point center = ``(x,y)`` with radii =
    ``r1,r2`` and angle ``angle``.  Type ``ellipse.options`` to see all
    options.

    INPUT:

    - ``center`` - 2-tuple of real numbers - coordinates of the center

    - ``r1``, ``r2`` - positive real numbers - the radii of the ellipse

    - ``angle`` - real number (default: 0) - the angle between the first axis
      and the horizontal
    
    OPTIONS:

    - ``alpha`` - default: 1 - transparency

    - ``fill`` - default: False - whether to fill the ellipse or not

    - ``thickness`` - default: 1 - thickness of the line

    - ``rgbcolor`` - default: (0,0,0) - color of the ellipse 
      (overwrites ``edgecolor`` and ``facecolor``)

    - ``linestyle`` - default: 'solid'

    - ``edgecolor`` - default: 'black' - color of the contour

    - ``facecolor`` - default: 'red' - color of the filling

    EXAMPLES:

    An ellipse centered at (0,0) with major and minor axes of lengths 2 and 1::

        sage: ellipse((0,0),2,1)

    More complicated examples with tilted axes and drawing options::

        sage: ellipse((0,0),3,1,pi/6,fill=True,alpha=0.3)

    ::

        sage: ellipse((0,0),3,1,pi/6,fill=True,edgecolor='blue',facecolor='red')

    The default aspect ratio for ellipses is 1.0::

        sage: ellipse((0,0),2,1).aspect_ratio()
        1.0

    One cannot yet plot ellipses in 3D::

        sage: ellipse((0,0,0),2,1)
        Traceback (most recent call last):
        ...
        NotImplementedError: plotting ellipse in 3D is not implemented
    """
    from sage.plot.plot import Graphics
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(Ellipse(center[0],center[1],r1,r2,angle,options))
    if len(center)==2:
        return g
    elif len(center)==3:
        raise NotImplementedError, "plotting ellipse in 3D is not implemented"
Esempio n. 20
0
    z, ranges = setup_for_eval_on_grid([f, g], [xrange, yrange],
                                       options['plot_points'])
    f, g = z

    xpos_array, ypos_array, xvec_array, yvec_array = [], [], [], []
    for x in xsrange(*ranges[0], include_endpoint=True):
        for y in xsrange(*ranges[1], include_endpoint=True):
            xpos_array.append(x)
            ypos_array.append(y)
            xvec_array.append(f(x, y))
            yvec_array.append(g(x, y))

    import numpy
    xvec_array = numpy.ma.masked_invalid(numpy.array(xvec_array, dtype=float))
    yvec_array = numpy.ma.masked_invalid(numpy.array(yvec_array, dtype=float))
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(
        PlotField(xpos_array, ypos_array, xvec_array, yvec_array, options))
    return g


def plot_slope_field(f, xrange, yrange, **kwds):
    r"""
    ``plot_slope_field`` takes a function of two variables xvar and yvar
    (for instance, if the variables are `x` and `y`, take `f(x,y)`), and at
    representative points `(x_i,y_i)` between xmin, xmax, and ymin, ymax
    respectively, plots a line with slope `f(x_i,y_i)` (see below).

    ``plot_slope_field(f, (xvar, xmin, xmax), (yvar, ymin, ymax))``
Esempio n. 21
0
def circle(center, radius, **options):
    """
    Return a circle at a point center = `(x,y)` (or `(x,y,z)` and 
    parallel to the `xy`-plane) with radius = `r`.  Type 
    ``circle.options`` to see all options.
    
    OPTIONS:

    - ``alpha`` - default: 1

    - ``fill`` - default: False

    - ``thickness`` - default: 1

    - ``rgbcolor`` - default: (0,0,0)

    - ``linestyle`` - default: 'solid' (2D plotting only)

    - ``edgecolor`` - default: 'black' (2D plotting only)

    - ``facecolor`` - default: 'red' (2D plotting only, useful only
      if fill=True)

    - ``legend_label`` -- the label for this item in the legend

    EXAMPLES::

        sage: c = circle((1,1), 1, rgbcolor=(1,0,0))
        sage: c

    We can also use this command to plot three-dimensional circles parallel
    to the `xy`-plane::

        sage: c = circle((1,1,3), 1, rgbcolor=(1,0,0))
        sage: c
        sage: type(c)
        <class 'sage.plot.plot3d.base.TransformGroup'>

    To correct the aspect ratio of certain graphics, it is necessary
    to show with a ``figsize`` of square dimensions::

        sage: c.show(figsize=[5,5],xmin=-1,xmax=3,ymin=-1,ymax=3)

    Here we make a more complicated plot, with many circles of different colors::

        sage: g = Graphics()
        sage: step=6; ocur=1/5; paths=16;
        sage: PI = math.pi    # numerical for speed -- fine for graphics
        sage: for r in range(1,paths+1):
        ...       for x,y in [((r+ocur)*math.cos(n), (r+ocur)*math.sin(n)) for n in srange(0, 2*PI+PI/step, PI/step)]:
        ...           g += circle((x,y), ocur, rgbcolor=hue(r/paths))
        ...       rnext = (r+1)^2
        ...       ocur = (rnext-r)-ocur
        ...
        sage: g.show(xmin=-(paths+1)^2, xmax=(paths+1)^2, ymin=-(paths+1)^2, ymax=(paths+1)^2, figsize=[6,6])

    Note that the ``rgbcolor`` option overrides the other coloring options.
    This produces red fill in a blue circle::

        sage: circle((2,3), 1, fill=True, edgecolor='blue')

    This produces an all-green filled circle::

        sage: circle((2,3), 1, fill=True, edgecolor='blue', rgbcolor='green')

    The option ``hue`` overrides *all* other options, so be careful with its use.
    This produces a purplish filled circle::

        sage: circle((2,3), 1, fill=True, edgecolor='blue', rgbcolor='green', hue=.8)

    And a circle with a legend::

        sage: circle((4,5), 1, rgbcolor='yellow', fill=True, legend_label='the sun').show(xmin=0, ymin=0)

    Extra options will get passed on to show(), as long as they are valid::

        sage: circle((0, 0), 2, figsize=[10,10]) # That circle is huge!

    ::

        sage: circle((0, 0), 2).show(figsize=[10,10]) # These are equivalent

    TESTS:

    We cannot currently plot circles in more than three dimensions::

        sage: circle((1,1,1,1), 1, rgbcolor=(1,0,0))
        Traceback (most recent call last):
        ...
        ValueError: The center of a plotted circle should have two or three coordinates.

    The default aspect ratio for a circle is 1.0::

        sage: P = circle((1,1), 1)
        sage: P.aspect_ratio()
        1.0
    """
    from sage.plot.plot import Graphics
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(Circle(center[0], center[1], radius, options))
    if options['legend_label']:
        g.legend(True)
    if len(center)==2:
        return g
    elif len(center)==3:
        return g[0].plot3d(z=center[2])
    else:
        raise ValueError, 'The center of a plotted circle should have two or three coordinates.'
Esempio n. 22
0
def arrow2d(tailpoint=None, headpoint=None, path=None, **options):
    """
    If tailpoint and headpoint are provided, returns an arrow from (xmin, ymin) 
    to (xmax, ymax).  If tailpoint or headpoint is None and path is not None,
    returns an arrow along the path.  (See further info on paths in bezier_path).

    INPUT:

    - ``tailpoint`` - the starting point of the arrow

    - ``headpoint`` - where the arrow is pointing to

    - ``path`` - the list of points and control points (see bezier_path for detail) that 
      the arrow will follow from source to destination

    - ``head`` - 0, 1 or 2, whether to draw the head at the start (0), end (1) or both (2)
      of the path (using 0 will swap headpoint and tailpoint).  This is ignored
      in 3D plotting.

    - ``width`` - (default: 2) the width of the arrow shaft, in points

    - ``color`` - (default: (0,0,1)) the color of the arrow (as an RGB tuple or a string)

    - ``hue`` - the color of the arrow (as a number)

    - ``arrowsize`` - the size of the arrowhead

    - ``arrowshorten`` - the length in points to shorten the arrow (ignored if using path
      parameter)

    - ``legend_label`` - the label for this item in the legend 

    - ``zorder`` - the layer level to draw the arrow-- note that this is ignored in 3D
      plotting.

    EXAMPLES:

    A straight, blue arrow::

       sage: arrow2d((1, 1), (3, 3))
    
    Make a red arrow::

       sage: arrow2d((-1, -1), (2, 3), color=(1,0,0))
       sage: arrow2d((-1, -1), (2, 3), color='red')

    You can change the width of an arrow::

        sage: arrow2d((1, 1), (3, 3), width=5, arrowsize=15)

    A pretty circle of arrows::

        sage: sum([arrow2d((0,0), (cos(x),sin(x)), hue=x/(2*pi)) for x in [0..2*pi,step=0.1]])

    If we want to draw the arrow between objects, for example, the
    boundaries of two lines, we can use the arrowshorten option
    to make the arrow shorter by a certain number of points::

        sage: line([(0,0),(1,0)],thickness=10)+line([(0,1),(1,1)], thickness=10)+arrow2d((0.5,0),(0.5,1), arrowshorten=10,rgbcolor=(1,0,0))

    If BOTH headpoint and tailpoint are None, then an empty plot is returned::
    
        sage: arrow2d(headpoint=None, tailpoint=None)
        
    
    We can also draw an arrow with a legend::

        sage: arrow((0,0), (0,2), legend_label='up')

    Extra options will get passed on to show(), as long as they are valid::
 
        sage: arrow2d((-2, 2), (7,1), frame=True)
        sage: arrow2d((-2, 2), (7,1)).show(frame=True)
    """
    from sage.plot.plot import Graphics
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    if headpoint is not None and tailpoint is not None:
        xtail, ytail = tailpoint
        xhead, yhead = headpoint
        g.add_primitive(Arrow(xtail, ytail, xhead, yhead, options=options))
    elif path is not None:
        g.add_primitive(CurveArrow(path, options=options))
    elif tailpoint is None and headpoint is None:
        return g
    else:
        raise TypeError(
            'Arrow requires either both headpoint and tailpoint or a path parameter.'
        )
    if options['legend_label']:
        g.legend(True)
    return g
Esempio n. 23
0
    def plot(self, size=[[0],[0]], projection='usual', simple_roots=True, fundamental_weights=True, alcovewalks=[]):
        r"""
        Return a graphics object built from a space of weight(space/lattice).
        There is a different technic to plot if the Cartan type is affine or not.
        The graphics returned is a Graphics object.

        This function is experimental, and is subject to short term evolutions.

        EXAMPLES::

          By default, the plot returned has no axes and the ratio between axes is 1.
            sage: G = RootSystem(['C',2]).weight_lattice().plot()
            sage: G.axes(True)
            sage: G.set_aspect_ratio(2)

          For a non affine Cartan type, the plot method work for type with 2 generators,
          it will draw the hyperlane(line for this dimension) accrow the fundamentals weights.
            sage: G = RootSystem(['A',2]).weight_lattice().plot()
            sage: G = RootSystem(['B',2]).weight_lattice().plot()
            sage: G = RootSystem(['G',2]).weight_lattice().plot()

          The plot returned has a size of one fundamental polygon by default. We can
          ask plot to give a bigger plot by using the argument size
            sage: G = RootSystem(['G',2,1]).weight_space().plot(size = [[0..1],[-1..1]])
            sage: G = RootSystem(['A',2,1]).weight_space().plot(size = [[-1..1],[-1..1]])

          A very important argument is the projection which will draw the plot. There are
          some usual projections is this method. If you want to draw in the plane a very
          special Cartan type, Sage will ask you to specify the projection. The projection
          is a matrix over a ring. In practice, calcul over float is a good way to draw.
            sage: L = RootSystem(['A',2,1]).weight_space()
            sage: G = L.plot(projection=matrix(RR, [[0,0.5,-0.5],[0,0.866,0.866]]))
            sage: G = RootSystem(['C',2,1]).weight_space().plot()

          By default, the plot method draw the simple roots, this can be disabled by setting
          the argument simple_roots=False
            sage: G = RootSystem(['A',2]).weight_space().plot(simple_roots=False)

          By default, the plot method draw the fundamental weights,this can be disabled by
          setting the argument fundamental_weights=False
            sage: G = RootSystem(['A',2]).weight_space().plot(fundamental_weights=False, simple_roots=False)

          There is in a plot an argument to draw alcoves walks. The good way to do this is
          to use the crystals theory. the plot method contains only the drawing part...
            sage: L = RootSystem(['A',2,1]).weight_space()
            sage: G = L.plot(size=[[-1..1],[-1..1]],alcovewalks=[[0,2,0,1,2,1,2,0,2,1]])
        """

        from sage.plot.plot import Graphics
        from sage.plot.line import line
        from cartan_type import CartanType
        from sage.matrix.constructor import matrix
        from sage.rings.all import QQ, RR
        from sage.plot.arrow import arrow
        from sage.plot.point import point

        # We begin with an empty plot G
        G = Graphics()

        ct = self.cartan_type()
        n = ct.n

        # Define a set of colors
        # TODO : Colors in option ?
        colors=[(0,1,0),(1,0,0),(0,0,1),(1,1,0),(0,1,1),(1,0,1)]

        # plot the affine types:
        if ct.is_affine():

            # Check the projection
            # TODO : try to have usual_projection for main plotable types
            if projection == 'usual':
                if ct == CartanType(['A',2,1]):
                    projection = matrix(RR, [[0,0.5,-0.5],[0,0.866,0.866]])
                elif ct == CartanType(['C',2,1]):
                    projection = matrix(QQ, [[0,1,1],[0,0,1]])
                elif ct == CartanType(['G',2,1]):
                    projection = matrix(RR, [[0,0.5,0],[0,0.866,1.732]])
                else:
                    raise 'There is no usual projection for this Cartan type, you have to give one in argument'

            assert(n + 1 == projection.ncols())
            assert(2 == projection.nrows())

            # Check the size is correct with the lattice
            assert(len(size) == n)

            # Select the center of the translated fundamental polygon to plot
            translation_factors = ct.translation_factors()
            simple_roots = self.simple_roots()
            translation_vectors = [translation_factors[i]*simple_roots[i] for i in ct.classical().index_set()]

            initial = [[]]
            for i in range(n):
                prod_list = []
                for elem in size[i]:
                    for partial_list in initial:
                        prod_list.append( [elem]+partial_list );
                initial = prod_list;

            part_lattice = []
            for combinaison in prod_list:
                elem_lattice = self.zero()
                for i in range(n):
                    elem_lattice = elem_lattice + combinaison[i]*translation_vectors[i]
                part_lattice.append(elem_lattice)

            # Get the vertices of the fundamental alcove
            fundamental_weights = self.fundamental_weights()
            vertices = map(lambda x: (1/x.level())*x, fundamental_weights.list())

            # Recup the group which act on the fundamental polygon
            classical = self.weyl_group().classical()

            for center in part_lattice:
                for w in classical:
                    # for each center of polygon and each element of classical
                    # parabolic subgroup, we have to draw an alcove.

                    #first, iterate over pairs of fundamental weights, drawing lines border of polygons:
                    for i in range(1,n+1):
                        for j in range(i+1,n+1):
                            p1=projection*((w.action(vertices[i])).to_vector() + center.to_vector())
                            p2=projection*((w.action(vertices[j])).to_vector() + center.to_vector())
                            G+=line([p1,p2],rgbcolor=(0,0,0),thickness=2)

                    #next, get all lines from point to a fundamental weight, that separe different
                    #chanber in a same polygon (important: associate a color with a fundamental weight)
                    pcenter = projection*(center.to_vector())
                    for i in range(1,n+1):
                        p3=projection*((w.action(vertices[i])).to_vector() + center.to_vector())
                        G+=line([p3,pcenter], rgbcolor=colors[n-i+1])

            #Draw alcovewalks
            #FIXME : The good way to draw this is to use the alcoves walks works made in Cristals
            #The code here just draw like example and import the good things.
            rho = (1/self.rho().level())*self.rho()
            W = self.weyl_group()
            for walk in alcovewalks:
                target = W.from_reduced_word(walk).action(rho)
                for i in range(len(walk)):
                    walk.pop()
                    origin = W.from_reduced_word(walk).action(rho)
                    G+=arrow(projection*(origin.to_vector()),projection*(target.to_vector()), rgbcolor=(0.6,0,0.6), width=1, arrowsize=5)
                    target = origin

        else:
            # non affine plot

            # Check the projection
            # TODO : try to have usual_projection for main plotable types
            if projection == 'usual':
                if ct == CartanType(['A',2]):
                    projection = matrix(RR, [[0.5,-0.5],[0.866,0.866]])
                elif ct == CartanType(['B',2]):
                    projection = matrix(QQ, [[1,0],[1,1]])
                elif ct == CartanType(['C',2]):
                    projection = matrix(QQ, [[1,1],[0,1]])
                elif ct == CartanType(['G',2]):
                    projection = matrix(RR, [[0.5,0],[0.866,1.732]])
                else:
                    raise 'There is no usual projection for this Cartan type, you have to give one in argument'

            # Get the fundamental weights
            fundamental_weights = self.fundamental_weights()
            WeylGroup = self.weyl_group()

            #Draw not the alcove but the cones delimited by the hyperplanes
            #The size of the line depend of the fundamental weights.
            pcenter = projection*(self.zero().to_vector())
            for w in WeylGroup:
                for i in range(1,n+1):
                    p3=3*projection*((w.action(fundamental_weights[i])).to_vector())
                    G+=line([p3,pcenter], rgbcolor=colors[n-i+1])

        #Draw the simple roots
        if simple_roots:
            SimpleRoots = self.simple_roots()
            if ct.is_affine():
                G+=arrow((0,0), projection*(SimpleRoots[0].to_vector()), rgbcolor=(0,0,0))
            for j in range(1,n+1):
                G+=arrow((0,0),projection*(SimpleRoots[j].to_vector()), rgbcolor=colors[j])

        #Draw the fundamental weights
        if fundamental_weights:
            FundWeight = self.fundamental_weights()
            for j in range(1,n+1):
                G+=point(projection*(FundWeight[j].to_vector()), rgbcolor=colors[j], pointsize=60)

        G.set_aspect_ratio(1)
        G.axes(False)
        return G
Esempio n. 24
0
def ellipse(center, r1, r2, angle=0, **options):
    """
    Return an ellipse centered at a point center = ``(x,y)`` with radii =
    ``r1,r2`` and angle ``angle``.  Type ``ellipse.options`` to see all
    options.

    INPUT:

    - ``center`` - 2-tuple of real numbers - coordinates of the center

    - ``r1``, ``r2`` - positive real numbers - the radii of the ellipse

    - ``angle`` - real number (default: 0) - the angle between the first axis
      and the horizontal
    
    OPTIONS:

    - ``alpha`` - default: 1 - transparency

    - ``fill`` - default: False - whether to fill the ellipse or not

    - ``thickness`` - default: 1 - thickness of the line

    - ``rgbcolor`` - default: (0,0,0) - color of the ellipse 
      (overwrites ``edgecolor`` and ``facecolor``)

    - ``linestyle`` - default: 'solid'

    - ``edgecolor`` - default: 'black' - color of the contour

    - ``facecolor`` - default: 'red' - color of the filling

    EXAMPLES:

    An ellipse centered at (0,0) with major and minor axes of lengths 2 and 1::

        sage: ellipse((0,0),2,1)

    More complicated examples with tilted axes and drawing options::

        sage: ellipse((0,0),3,1,pi/6,fill=True,alpha=0.3)

    ::

        sage: ellipse((0,0),3,1,pi/6,fill=True,edgecolor='blue',facecolor='red')

    The default aspect ratio for ellipses is 1.0::

        sage: ellipse((0,0),2,1).aspect_ratio()
        1.0

    One cannot yet plot ellipses in 3D::

        sage: ellipse((0,0,0),2,1)
        Traceback (most recent call last):
        ...
        NotImplementedError: plotting ellipse in 3D is not implemented
    """
    from sage.plot.plot import Graphics
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(Ellipse(center[0], center[1], r1, r2, angle, options))
    if len(center) == 2:
        return g
    elif len(center) == 3:
        raise NotImplementedError, "plotting ellipse in 3D is not implemented"
Esempio n. 25
0
def matrix_plot(mat, **options):
    r"""
    A plot of a given matrix or 2D array.
    
    If the matrix is dense, each matrix element is given a different
    color value depending on its relative size compared to the other
    elements in the matrix.  If the matrix is sparse, colors only
    indicate whether an element is nonzero or zero, so the plot
    represents the sparsity pattern of the matrix.

    The tick marks drawn on the frame axes denote the row numbers
    (vertical ticks) and the column numbers (horizontal ticks) of the
    matrix.

    INPUT:

    - ``mat`` - a 2D matrix or array

    The following input must all be passed in as named parameters, if
    default not used:

    - ``cmap`` - a colormap (default: 'gray'), the name of
      a predefined colormap, a list of colors,
      or an instance of a matplotlib Colormap.
      Type: ``import matplotlib.cm; matplotlib.cm.datad.keys()``
      for available colormap names.

    - ``colorbar`` -- boolean (default: False) Show a colorbar or not (dense matrices only).
    
      The following options are used to adjust the style and placement
      of colorbars.  They have no effect if a colorbar is not shown.

      - ``colorbar_orientation`` -- string (default: 'vertical'),
        controls placement of the colorbar, can be either 'vertical'
        or 'horizontal'

      - ``colorbar_format`` -- a format string, this is used to format
        the colorbar labels.

      - ``colorbar_options`` -- a dictionary of options for the matplotlib
        colorbar API.  Documentation for the :mod:`matplotlib.colorbar` module
        has details.

    - ``norm`` - If None (default), the value range is scaled to the interval
      [0,1].  If 'value', then the actual value is used with no
      scaling.  A :class:`matplotlib.colors.Normalize` instance may
      also passed.

    - ``vmin`` - The minimum value (values below this are set to this value)

    - ``vmax`` - The maximum value (values above this are set to this value)

    - ``origin`` - If 'upper' (default), the first row of the matrix
      is on the top of the graph.  If 'lower', the first row is on the
      bottom of the graph.

    - ``subdivisions`` - If True, plot the subdivisions of the matrix as lines.

    - ``subdivision_boundaries`` - a list of lists in the form
      ``[row_subdivisions, column_subdivisions]``, which specifies
      the row and column subdivisions to use.  If not specified,
      defaults to the matrix subdivisions
    
    - ``subdivision_style`` - a dictionary of properties passed
      on to the :func:`~sage.plot.line.line2d` command for plotting
      subdivisions.  If this is a two-element list or tuple, then it 
      specifies the styles of row and column divisions, respectively.

    EXAMPLES:
    
    A matrix over `\ZZ` colored with different grey levels::
    
        sage: matrix_plot(matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]]))

    Here we make a random matrix over `\RR` and use ``cmap='hsv'``
    to color the matrix elements different RGB colors::

        sage: matrix_plot(random_matrix(RDF, 50), cmap='hsv')

    By default, entries are scaled to the interval [0,1] before
    determining colors from the color map.  That means the two plots
    below are the same::

        sage: P = matrix_plot(matrix(2,[1,1,3,3]))
        sage: Q = matrix_plot(matrix(2,[2,2,3,3]))
        sage: P; Q

    However, we can specify which values scale to 0 or 1 with the
    ``vmin`` and ``vmax`` parameters (values outside the range are
    clipped).  The two plots below are now distinguished::

        sage: P = matrix_plot(matrix(2,[1,1,3,3]), vmin=0, vmax=3, colorbar=True)
        sage: Q = matrix_plot(matrix(2,[2,2,3,3]), vmin=0, vmax=3, colorbar=True)
        sage: P; Q

    We can also specify a norm function of 'value', which means that
    there is no scaling performed::
    
        sage: matrix_plot(random_matrix(ZZ,10)*.05, norm='value', colorbar=True)

    Matrix subdivisions can be plotted as well::
    
        sage: m=random_matrix(RR,10)
        sage: m.subdivide([2,4],[6,8])
        sage: matrix_plot(m, subdivisions=True, subdivision_style=dict(color='red',thickness=3))
    
    You can also specify your own subdivisions and separate styles
    for row or column subdivisions::
    
        sage: m=random_matrix(RR,10)
        sage: matrix_plot(m, subdivisions=True, subdivision_boundaries=[[2,4],[6,8]], subdivision_style=[dict(color='red',thickness=3),dict(linestyle='--',thickness=6)])

    Generally matrices are plotted with the (0,0) entry in the upper
    left.  However, sometimes if we are plotting an image, we'd like
    the (0,0) entry to be in the lower left.  We can do that with the
    ``origin`` argument::

        sage: matrix_plot(identity_matrix(100), origin='lower')

    Another random plot, but over `\GF{389}`::

        sage: m = random_matrix(GF(389), 10)
        sage: matrix_plot(m, cmap='Oranges')

    It also works if you lift it to the polynomial ring::

        sage: matrix_plot(m.change_ring(GF(389)['x']), cmap='Oranges')

    We have several options for colorbars::

        sage: matrix_plot(random_matrix(RDF, 50), colorbar=True, colorbar_orientation='horizontal')

    ::

        sage: matrix_plot(random_matrix(RDF, 50), colorbar=True, colorbar_format='%.3f')

    The length of a color bar and the length of the adjacent
    matrix plot dimension may be quite different.  This example
    shows how to adjust the length of the colorbar by passing a
    dictionary of options to the matplotlib colorbar routines.  ::

        sage: m = random_matrix(ZZ, 40, 80, x=-10, y=10)
        sage: m.plot(colorbar=True, colorbar_orientation='vertical',
        ...          colorbar_options={'shrink':0.50})

    Here we plot a random sparse matrix::

        sage: sparse = matrix(dict([((randint(0, 10), randint(0, 10)), 1) for i in xrange(100)]))
        sage: matrix_plot(sparse)

    ::

        sage: A=random_matrix(ZZ,100000,density=.00001,sparse=True)
        sage: matrix_plot(A,marker=',')

    As with dense matrices, sparse matrix entries are automatically
    converted to floating point numbers before plotting.  Thus the
    following works::

        sage: b=random_matrix(GF(2),200,sparse=True,density=0.01)
        sage: matrix_plot(b)

    While this returns an error::

        sage: b=random_matrix(CDF,200,sparse=True,density=0.01)
        sage: matrix_plot(b)
        Traceback (most recent call last):
        ...
        ValueError: can not convert entries to floating point numbers

    To plot the absolute value of a complex matrix, use the
    ``apply_map`` method::

        sage: b=random_matrix(CDF,200,sparse=True,density=0.01)
        sage: matrix_plot(b.apply_map(abs))

    Plotting lists of lists also works::

        sage: matrix_plot([[1,3,5,1],[2,4,5,6],[1,3,5,7]])

    As does plotting of NumPy arrays::

        sage: import numpy
        sage: matrix_plot(numpy.random.rand(10, 10))

    TESTS::

        sage: P.<t> = RR[]
        sage: matrix_plot(random_matrix(P, 3, 3))
        Traceback (most recent call last):
        ...
        TypeError: cannot coerce nonconstant polynomial to float

    ::

        sage: matrix_plot([1,2,3])
        Traceback (most recent call last):
        ...
        TypeError: mat must be a Matrix or a two dimensional array

    ::

        sage: matrix_plot([[sin(x), cos(x)], [1, 0]])
        Traceback (most recent call last):
        ...
        ValueError: can not convert entries to floating point numbers

    Test that sparse matrices also work with subdivisions::

        sage: matrix_plot(sparse, subdivisions=True, subdivision_boundaries=[[2,4],[6,8]])
    """
    import numpy as np
    import scipy.sparse as scipysparse
    from sage.plot.plot import Graphics
    from sage.matrix.all import is_Matrix
    from sage.rings.all import RDF
    orig_mat=mat
    if is_Matrix(mat):
        sparse = mat.is_sparse()
        if sparse:
            entries = list(mat._dict().items())
            try:
                data = np.asarray([d for _,d in entries], dtype=float)
            except:
                raise ValueError, "can not convert entries to floating point numbers"
            positions = np.asarray([[row for (row,col),_ in entries], 
                                    [col for (row,col),_ in entries]], dtype=int)
            mat = scipysparse.coo_matrix((data,positions), shape=(mat.nrows(), mat.ncols()))
        else:
            mat = mat.change_ring(RDF).numpy()
    elif hasattr(mat, 'tocoo'):
        sparse = True
    else:
        sparse = False


    try:
        if sparse:
            xy_data_array = mat
        else:
            xy_data_array = np.asarray(mat, dtype = float)
    except TypeError:
        raise TypeError, "mat must be a Matrix or a two dimensional array"
    except ValueError:
        raise ValueError, "can not convert entries to floating point numbers"

    if len(xy_data_array.shape) < 2:
        raise TypeError, "mat must be a Matrix or a two dimensional array"

    xrange = (0, xy_data_array.shape[1])
    yrange = (0, xy_data_array.shape[0])

    if options['subdivisions'] and options['subdivision_options']['boundaries'] is None:
        options['subdivision_options']['boundaries']=orig_mat.get_subdivisions()

    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(MatrixPlot(xy_data_array, xrange, yrange, options))
    return g
Esempio n. 26
0
def text(string, xy, **options):
    r"""
    Returns a 2D text graphics object at the point `(x,y)`.
    
    Type ``text.options`` for a dictionary of options for 2D text.

    2D OPTIONS:

    - ``fontsize`` - How big the text is

    - ``rgbcolor`` - The color as an RGB tuple

    - ``hue`` - The color given as a hue

    - ``rotation`` - How to rotate the text: angle in degrees, vertical, horizontal

    - ``vertical_alignment`` - How to align vertically: top, center, bottom

    - ``horizontal_alignment`` - How to align horizontally: left, center, right

    - ``axis_coords`` - (default: False) if True, use axis coordinates, so that
      (0,0) is the lower left and (1,1) upper right, regardless of the x and y
      range of plotted values. 

    EXAMPLES::

        sage: text("Sage is really neat!!",(2,12))

    The same text in larger font and colored red::

        sage: text("Sage is really neat!!",(2,12),fontsize=20,rgbcolor=(1,0,0))

    Same text but guaranteed to be in the lower left no matter what::

        sage: text("Sage is really neat!!",(0,0), axis_coords=True, horizontal_alignment='left')

    Same text rotated around the left, bottom corner of the text::

        sage: text("Sage is really neat!!",(0,0), rotation=45.0, horizontal_alignment='left', vertical_alignment='bottom')

    Same text oriented vertically::

        sage: text("Sage is really neat!!",(0,0), rotation="vertical")

    You can also align text differently::

        sage: t1 = text("Hello",(1,1), vertical_alignment="top")
        sage: t2 = text("World", (1,0.5), horizontal_alignment="left")
        sage: t1 + t2   # render the sum

    You can save text as part of PDF output::

        sage: text("sage", (0,0), rgbcolor=(0,0,0)).save(SAGE_TMP + 'a.pdf')

    Text must be 2D (use the text3d command for 3D text)::

        sage: t = text("hi",(1,2,3))
        Traceback (most recent call last):
        ...
        ValueError: use text3d instead for text in 3d
        sage: t = text3d("hi",(1,2,3))

    Extra options will get passed on to show(), as long as they are valid::
    
        sage: text("MATH IS AWESOME", (0, 0), fontsize=40, axes=False)
        sage: text("MATH IS AWESOME", (0, 0), fontsize=40).show(axes=False) # These are equivalent
    """
    try:
        x, y = xy
    except ValueError:
        if isinstance(xy, (list, tuple)) and len(xy) == 3:
            raise ValueError, "use text3d instead for text in 3d"
        raise
    from sage.plot.plot import Graphics
    options['rgbcolor'] = to_mpl_color(options['rgbcolor'])
    point = (float(x), float(y))
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore='fontsize'))
    g.add_primitive(Text(string, point, options))
    return g
Esempio n. 27
0
def bezier_path(path, **options):
    """
    Returns a Graphics object of a Bezier path corresponding to the
    path parameter.  The path is a list of curves, and each curve is
    a list of points.  Each point is a tuple ``(x,y)``.
    
    The first curve contains the endpoints as the first and last point 
    in the list.  All other curves assume a starting point given by the
    last entry in the preceding list, and take the last point in the list
    as their opposite endpoint.  A curve can have 0, 1 or 2 control points
    listed between the endpoints.  In the input example for path below, 
    the first and second curves have 2 control points, the third has one,
    and the fourth has no control points:    
    
    path = [[p1, c1, c2, p2], [c3, c4, p3], [c5, p4], [p5], ...]
    
    In the case of no control points, a straight line will be drawn
    between the two endpoints.  If one control point is supplied, then 
    the curve at each of the endpoints will be tangent to the line from
    that endpoint to the control point.  Similarly, in the case of two 
    control points, at each endpoint the curve will be tangent to the line
    connecting that endpoint with the control point immediately after or
    immediately preceding it in the list.
    
    So in our example above, the curve between p1 and p2 is tangent to the
    line through p1 and c1 at p1, and tangent to the line through p2 and c2
    at p2.  Similarly, the curve between p2 and p3 is tangent to line(p2,c3)
    at p2 and tangent to line(p3,c4) at p3.  Curve(p3,p4) is tangent to 
    line(p3,c5) at p3 and tangent to line(p4,c5) at p4.  Curve(p4,p5) is a
    straight line.
    
    INPUT:

    - ``path`` -- a list of lists of tuples (see above)
    - ``alpha`` -- default: 1
    - ``fill`` -- default: False
    - ``thickness`` -- default: 1
    - ``linestyle`` -- default: 'solid'
    - ``rbgcolor`` -- default: (0,0,0)
    - ``zorder`` -- the layer in which to draw
        
    EXAMPLES::

        sage: path = [[(0,0),(.5,.1),(.75,3),(1,0)],[(.5,1),(.5,0)],[(.2,.5)]]
        sage: b = bezier_path(path, linestyle='dashed', rgbcolor='green')
        sage: b

    To construct a simple curve, create a list containing a single list::
        
        sage: path = [[(0,0),(.5,1),(1,0)]]
        sage: curve = bezier_path(path, linestyle='dashed', rgbcolor='green')
        sage: curve

    Extra options will get passed on to :meth:`~sage.plot.plot.Graphics.show`, as long as they are valid::

        sage: bezier_path([[(0,1),(.5,0),(1,1)]], fontsize=50)
        sage: bezier_path([[(0,1),(.5,0),(1,1)]]).show(fontsize=50) # These are equivalent
    """
    from sage.plot.plot import Graphics
    g = Graphics()
    g._set_extra_kwds(g._extract_kwds_for_show(options))
    g.add_primitive(BezierPath(path, options))
    return g
Esempio n. 28
0
def disk(point, radius, angle, **options):
    r"""
    A disk (that is, a sector or wedge of a circle) with center
    at a point = `(x,y)` (or `(x,y,z)` and parallel to the 
    `xy`-plane) with radius = `r` spanning (in radians) 
    angle=`(rad1, rad2)`.

    Type ``disk.options`` to see all options.

    EXAMPLES:

    Make some dangerous disks::
    
        sage: bl = disk((0.0,0.0), 1, (pi, 3*pi/2), color='yellow')
        sage: tr = disk((0.0,0.0), 1, (0, pi/2), color='yellow')
        sage: tl = disk((0.0,0.0), 1, (pi/2, pi), color='black')
        sage: br = disk((0.0,0.0), 1, (3*pi/2, 2*pi), color='black')
        sage: P  = tl+tr+bl+br
        sage: P.show(xmin=-2,xmax=2,ymin=-2,ymax=2)

    The default aspect ratio is 1.0::

        sage: disk((0.0,0.0), 1, (pi, 3*pi/2)).aspect_ratio()
        1.0

    Another example of a disk::

        sage: bl = disk((0.0,0.0), 1, (pi, 3*pi/2), rgbcolor=(1,1,0))
        sage: bl.show(figsize=[5,5])

    Note that since ``thickness`` defaults to zero, it is best to change
    that option when using ``fill=False``::

        sage: disk((2,3), 1, (pi/4,pi/3), hue=.8, alpha=.3, fill=False, thickness=2)

    The previous two examples also illustrate using ``hue`` and ``rgbcolor``
    as ways of specifying the color of the graphic.

    We can also use this command to plot three-dimensional disks parallel
    to the `xy`-plane::

        sage: d = disk((1,1,3), 1, (pi,3*pi/2), rgbcolor=(1,0,0))
        sage: d
        sage: type(d)
        <type 'sage.plot.plot3d.index_face_set.IndexFaceSet'>

    Extra options will get passed on to ``show()``, as long as they are valid::

        sage: disk((0, 0), 5, (0, pi/2), xmin=0, xmax=5, ymin=0, ymax=5, figsize=(2,2), rgbcolor=(1, 0, 1))
        sage: disk((0, 0), 5, (0, pi/2), rgbcolor=(1, 0, 1)).show(xmin=0, xmax=5, ymin=0, ymax=5, figsize=(2,2)) # These are equivalent

    TESTS:

    We cannot currently plot disks in more than three dimensions::

        sage: d = disk((1,1,1,1), 1, (0,pi))
        Traceback (most recent call last):
        ...
        ValueError: The center point of a plotted disk should have two or three coordinates.
    """
    from sage.plot.plot import Graphics
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(Disk(point, radius, angle, options))
    if options['legend_label']:
        g.legend(True)
    if len(point)==2:
        return g
    elif len(point)==3:
        return g[0].plot3d(z=point[2])
    else:
        raise ValueError, 'The center point of a plotted disk should have two or three coordinates.'
Esempio n. 29
0
def contour_plot(f, xrange, yrange, **options):
    r"""    
    ``contour_plot`` takes a function of two variables, `f(x,y)`
    and plots contour lines of the function over the specified 
    ``xrange`` and ``yrange`` as demonstrated below.

    ``contour_plot(f, (xmin, xmax), (ymin, ymax), ...)``

    INPUT:

    - ``f`` -- a function of two variables

    - ``(xmin, xmax)`` -- 2-tuple, the range of ``x`` values OR 3-tuple
      ``(x,xmin,xmax)``

    - ``(ymin, ymax)`` -- 2-tuple, the range of ``y`` values OR 3-tuple
      ``(y,ymin,ymax)``

    The following inputs must all be passed in as named parameters:

    - ``plot_points``  -- integer (default: 100); number of points to plot
      in each direction of the grid.  For old computers, 25 is fine, but 
      should not be used to verify specific intersection points.

    - ``fill`` -- bool (default: ``True``), whether to color in the area
      between contour lines

    - ``cmap`` -- a colormap (default: ``'gray'``), the name of
      a predefined colormap, a list of colors or an instance of a matplotlib
      Colormap. Type: ``import matplotlib.cm; matplotlib.cm.datad.keys()``
      for available colormap names.

    - ``contours`` -- integer or list of numbers (default: ``None``):
      If a list of numbers is given, then this specifies the contour levels
      to use.  If an integer is given, then this many contour lines are
      used, but the exact levels are determined automatically. If ``None``
      is passed (or the option is not given), then the number of contour
      lines is determined automatically, and is usually about 5.

    - ``linewidths`` -- integer or list of integer (default: None), if
      a single integer all levels will be of the width given,
      otherwise the levels will be plotted with the width in the order
      given.  If the list is shorter than the number of contours, then
      the widths will be repeated cyclically.

    - ``linestyles`` -- string or list of strings (default: None), the
      style of the lines to be plotted, one of: solid, dashed,
      dashdot, or dotted.  If the list is shorter than the number of
      contours, then the styles will be repeated cyclically.

    - ``labels`` -- boolean (default: False) Show level labels or not.
 
      The following options are to adjust the style and placement of
      labels, they have no effect if no labels are shown.

      - ``label_fontsize`` -- integer (default: 9), the font size of the labels.

      - ``label_colors`` -- string or sequence of colors (default:
        None) If a string, gives the name of a single color with which
        to draw all labels.  If a sequence, gives the colors of the
        labels.  A color is a string giving the name of one or a
        3-tuple of floats.

      - ``label_inline`` -- boolean (default: False if fill is True,
        otherwise True), controls whether the underlying contour is
        removed or not.

      - ``label_inline_spacing`` -- integer (default: 3), When inline,
        this is the amount of contour that is removed from each side,
        in pixels.

      - ``label_fmt`` -- a format string (default: "%1.2f"), this is
        used to get the label text from the level.  This can also be a
        dictionary with the contour levels as keys and corresponding
        text string labels as values.  It can also be any callable which
        returns a string when called with a numeric contour level.

    - ``colorbar`` -- boolean (default: False) Show a colorbar or not.
    
      The following options are to adjust the style and placement of
      colorbars.  They have no effect if a colorbar is not shown.

      - ``colorbar_orientation`` -- string (default: 'vertical'),
        controls placement of the colorbar, can be either 'vertical'
        or 'horizontal'

      - ``colorbar_format`` -- a format string, this is used to format
        the colorbar labels.

      - ``colorbar_spacing`` -- string (default: 'proportional').  If
        'proportional', make the contour divisions proportional to
        values.  If 'uniform', space the colorbar divisions uniformly,
        without regard for numeric values.

    - ``legend_label`` -- the label for this item in the legend

    EXAMPLES:

    Here we plot a simple function of two variables.  Note that
    since the input function is an expression, we need to explicitly
    declare the variables in 3-tuples for the range::

        sage: x,y = var('x,y')
        sage: contour_plot(cos(x^2+y^2), (x, -4, 4), (y, -4, 4))
         
    Here we change the ranges and add some options::

        sage: x,y = var('x,y')
        sage: contour_plot((x^2)*cos(x*y), (x, -10, 5), (y, -5, 5), fill=False, plot_points=150)
        
    An even more complicated plot::

        sage: x,y = var('x,y')
        sage: contour_plot(sin(x^2 + y^2)*cos(x)*sin(y), (x, -4, 4), (y, -4, 4),plot_points=150)

    Some elliptic curves, but with symbolic endpoints.  In the first
    example, the plot is rotated 90 degrees because we switch the
    variables `x`, `y`::

        sage: x,y = var('x,y')
        sage: contour_plot(y^2 + 1 - x^3 - x, (y,-pi,pi), (x,-pi,pi))

    ::

        sage: contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi))

    We can play with the contour levels::

        sage: x,y = var('x,y')
        sage: f(x,y) = x^2 + y^2
        sage: contour_plot(f, (-2, 2), (-2, 2))

    ::

        sage: contour_plot(f, (-2, 2), (-2, 2), contours=2, cmap=[(1,0,0), (0,1,0), (0,0,1)])
 
    ::

        sage: contour_plot(f, (-2, 2), (-2, 2), contours=(0.1, 1.0, 1.2, 1.4), cmap='hsv')

    ::

        sage: contour_plot(f, (-2, 2), (-2, 2), contours=(1.0,), fill=False)

    ::

        sage: contour_plot(x-y^2,(x,-5,5),(y,-3,3),contours=[-4,0,1])

    We can change the style of the lines::

        sage: contour_plot(f, (-2,2), (-2,2), fill=False, linewidths=10)

    ::

        sage: contour_plot(f, (-2,2), (-2,2), fill=False, linestyles='dashdot')

    ::

        sage: P=contour_plot(x^2-y^2,(x,-3,3),(y,-3,3),contours=[0,1,2,3,4],\
        ...    linewidths=[1,5],linestyles=['solid','dashed'],fill=False)
        sage: P

    ::

        sage: P=contour_plot(x^2-y^2,(x,-3,3),(y,-3,3),contours=[0,1,2,3,4],\
        ...    linewidths=[1,5],linestyles=['solid','dashed'])
        sage: P

    We can add labels and play with them::

        sage: contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi),  fill=False, cmap='hsv', labels=True)

    ::

        sage: P=contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), fill=False, cmap='hsv',\
        ...     labels=True, label_fmt="%1.0f", label_colors='black')
        sage: P

    ::

        sage: P=contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), fill=False, cmap='hsv',labels=True,\
        ...    contours=[-4,0,4],  label_fmt={-4:"low", 0:"medium", 4: "hi"}, label_colors='black')
        sage: P

    ::

        sage: P=contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), fill=False, cmap='hsv',labels=True,\
        ...    contours=[-4,0,4],  label_fmt=lambda x: "$z=%s$"%x, label_colors='black', label_inline=True, \
        ...    label_fontsize=12)
        sage: P

    ::

        sage: P=contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), \
        ...    fill=False, cmap='hsv', labels=True, label_fontsize=18)
        sage: P

    ::

        sage: P=contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), \
        ...    fill=False, cmap='hsv', labels=True, label_inline_spacing=1)
        sage: P

    ::

        sage: P= contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), \
        ...    fill=False, cmap='hsv', labels=True, label_inline=False)
        sage: P
    
    We can change the color of the labels if so desired::

        sage: contour_plot(f, (-2,2), (-2,2), labels=True, label_colors='red')

    We can add a colorbar as well::

        sage: f(x,y)=x^2-y^2
        sage: contour_plot(f, (x,-3,3), (y,-3,3), colorbar=True)

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), colorbar=True,colorbar_orientation='horizontal')

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), contours=[-2,-1,4],colorbar=True)

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), contours=[-2,-1,4],colorbar=True,colorbar_spacing='uniform')

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), contours=[0,2,3,6],colorbar=True,colorbar_format='%.3f')

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), labels=True,label_colors='red',contours=[0,2,3,6],colorbar=True)

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), cmap='winter', contours=20, fill=False, colorbar=True)

    This should plot concentric circles centered at the origin::

        sage: x,y = var('x,y')
        sage: contour_plot(x^2+y^2-2,(x,-1,1), (y,-1,1))

    Extra options will get passed on to show(), as long as they are valid::

        sage: f(x, y) = cos(x) + sin(y)
        sage: contour_plot(f, (0, pi), (0, pi), axes=True)

    ::

        sage: contour_plot(f, (0, pi), (0, pi)).show(axes=True) # These are equivalent

    Note that with ``fill=False`` and grayscale contours, there is the 
    possibility of confusion between the contours and the axes, so use
    ``fill=False`` together with ``axes=True`` with caution::

        sage: contour_plot(f, (-pi, pi), (-pi, pi), fill=False, axes=True) 

    TESTS:

    To check that ticket 5221 is fixed, note that this has three curves, not two::

        sage: x,y = var('x,y')
        sage: contour_plot(x-y^2,(x,-5,5),(y,-3,3),contours=[-4,-2,0], fill=False)
    """
    from sage.plot.plot import Graphics
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid([f], [xrange, yrange], options['plot_points'])
    g = g[0]
    xrange,yrange=[r[:2] for r in ranges]
    
    xy_data_array = [[g(x, y) for x in xsrange(*ranges[0], include_endpoint=True)]
                              for y in xsrange(*ranges[1], include_endpoint=True)]

    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore=['xmin', 'xmax']))
    g.add_primitive(ContourPlot(xy_data_array, xrange, yrange, options))
    return g        
Esempio n. 30
0
def density_plot(f, xrange, yrange, **options):
    r"""    
    ``density_plot`` takes a function of two variables, `f(x,y)`
    and plots the height of of the function over the specified 
    ``xrange`` and ``yrange`` as demonstrated below.

    ``density_plot(f, (xmin, xmax), (ymin, ymax), ...)``

    INPUT:

    - ``f`` -- a function of two variables

    - ``(xmin, xmax)`` -- 2-tuple, the range of ``x`` values OR 3-tuple
      ``(x,xmin,xmax)``

    - ``(ymin, ymax)`` -- 2-tuple, the range of ``y`` values OR 3-tuple
      ``(y,ymin,ymax)``

    The following inputs must all be passed in as named parameters:

    - ``plot_points`` -- integer (default: 25); number of points to plot
      in each direction of the grid

    - ``cmap`` -- a colormap (type ``cmap_help()`` for more information).

    - ``interpolation`` -- string (default: ``'catrom'``), the interpolation
      method to use: ``'bilinear'``, ``'bicubic'``, ``'spline16'``,
      ``'spline36'``, ``'quadric'``, ``'gaussian'``, ``'sinc'``,
      ``'bessel'``, ``'mitchell'``, ``'lanczos'``, ``'catrom'``,
      ``'hermite'``, ``'hanning'``, ``'hamming'``, ``'kaiser'``
        

    EXAMPLES:

    Here we plot a simple function of two variables.  Note that
    since the input function is an expression, we need to explicitly
    declare the variables in 3-tuples for the range::

        sage: x,y = var('x,y')
        sage: density_plot(sin(x)*sin(y), (x, -2, 2), (y, -2, 2))
        
        
    Here we change the ranges and add some options; note that here
    ``f`` is callable (has variables declared), so we can use 2-tuple ranges::

        sage: x,y = var('x,y')
        sage: f(x,y) = x^2*cos(x*y)
        sage: density_plot(f, (x,-10,5), (y, -5,5), interpolation='sinc', plot_points=100)
        
    An even more complicated plot::

        sage: x,y = var('x,y')
        sage: density_plot(sin(x^2 + y^2)*cos(x)*sin(y), (x, -4, 4), (y, -4, 4), cmap='jet', plot_points=100)
        
    This should show a "spotlight" right on the origin::

        sage: x,y = var('x,y') 
        sage: density_plot(1/(x^10+y^10), (x, -10, 10), (y, -10, 10)) 
        
    Some elliptic curves, but with symbolic endpoints.  In the first
    example, the plot is rotated 90 degrees because we switch the
    variables `x`, `y`::

        sage: density_plot(y^2 + 1 - x^3 - x, (y,-pi,pi), (x,-pi,pi))

    ::

        sage: density_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi))

    Extra options will get passed on to show(), as long as they are valid::

        sage: density_plot(log(x) + log(y), (x, 1, 10), (y, 1, 10), dpi=20)

    ::

        sage: density_plot(log(x) + log(y), (x, 1, 10), (y, 1, 10)).show(dpi=20) # These are equivalent
    """
    from sage.plot.plot import Graphics
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid([f], [xrange, yrange], options['plot_points'])
    g = g[0]
    xrange,yrange=[r[:2] for r in ranges]

    xy_data_array = [[g(x, y) for x in xsrange(*ranges[0], include_endpoint=True)]
                              for y in xsrange(*ranges[1], include_endpoint=True)]

    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore=['xmin', 'xmax']))
    g.add_primitive(DensityPlot(xy_data_array, xrange, yrange, options))
    return g
Esempio n. 31
0
def polygon2d(points, **options):
    r"""
    Returns a 2-dimensional polygon defined by ``points``.

    Type ``polygon.options`` for a dictionary of the default 
    options for polygons.  You can change this to change 
    the defaults for all future polygons.  Use ``polygon.reset()`` 
    to reset to the default options.
    
    EXAMPLES:

    We create a purple-ish polygon::

        sage: polygon2d([[1,2], [5,6], [5,0]], rgbcolor=(1,0,1))

    By default, polygons are filled in, but we can make them
    without a fill as well::

        sage: polygon2d([[1,2], [5,6], [5,0]], fill=False)

    In either case, the thickness of the border can be controlled::

        sage: polygon2d([[1,2], [5,6], [5,0]], fill=False, thickness=4, color='orange')

    Some modern art -- a random polygon, with legend::

        sage: v = [(randrange(-5,5), randrange(-5,5)) for _ in range(10)]
        sage: polygon2d(v, legend_label='some form')

    A purple hexagon::

        sage: L = [[cos(pi*i/3),sin(pi*i/3)] for i in range(6)]
        sage: polygon2d(L, rgbcolor=(1,0,1))

    A green deltoid::

        sage: L = [[-1+cos(pi*i/100)*(1+cos(pi*i/100)),2*sin(pi*i/100)*(1-cos(pi*i/100))] for i in range(200)]
        sage: polygon2d(L, rgbcolor=(1/8,3/4,1/2))

    A blue hypotrochoid::

        sage: L = [[6*cos(pi*i/100)+5*cos((6/2)*pi*i/100),6*sin(pi*i/100)-5*sin((6/2)*pi*i/100)] for i in range(200)]
        sage: polygon2d(L, rgbcolor=(1/8,1/4,1/2))
        
    Another one::

        sage: n = 4; h = 5; b = 2
        sage: L = [[n*cos(pi*i/100)+h*cos((n/b)*pi*i/100),n*sin(pi*i/100)-h*sin((n/b)*pi*i/100)] for i in range(200)]
        sage: polygon2d(L, rgbcolor=(1/8,1/4,3/4))

    A purple epicycloid::

        sage: m = 9; b = 1
        sage: L = [[m*cos(pi*i/100)+b*cos((m/b)*pi*i/100),m*sin(pi*i/100)-b*sin((m/b)*pi*i/100)] for i in range(200)]
        sage: polygon2d(L, rgbcolor=(7/8,1/4,3/4))

    A brown astroid::

        sage: L = [[cos(pi*i/100)^3,sin(pi*i/100)^3] for i in range(200)]
        sage: polygon2d(L, rgbcolor=(3/4,1/4,1/4))

    And, my favorite, a greenish blob::

        sage: L = [[cos(pi*i/100)*(1+cos(pi*i/50)), sin(pi*i/100)*(1+sin(pi*i/50))] for i in range(200)]
        sage: polygon2d(L, rgbcolor=(1/8, 3/4, 1/2))

    This one is for my wife::

        sage: L = [[sin(pi*i/100)+sin(pi*i/50),-(1+cos(pi*i/100)+cos(pi*i/50))] for i in range(-100,100)]
        sage: polygon2d(L, rgbcolor=(1,1/4,1/2))

    Polygons have a default aspect ratio of 1.0::

        sage: polygon2d([[1,2], [5,6], [5,0]]).aspect_ratio()
        1.0

    AUTHORS:

    - David Joyner (2006-04-14): the long list of examples above.
    
    """
    from sage.plot.plot import xydata_from_point_list, Graphics
    if options["thickness"] is None:    # If the user did not specify thickness
        if options["fill"]:                 # If the user chose fill
            options["thickness"] = 0
        else:
            options["thickness"] = 1
    xdata, ydata = xydata_from_point_list(points)
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(Polygon(xdata, ydata, options))
    if options['legend_label']:
        g.legend(True)
    return g 
Esempio n. 32
0
def line2d(points, **options):
    r"""
    Create the line through the given list of points.

    Type \code{line2d.options} for a dictionary of the default options for 
    lines.  You can change this to change the defaults for all future
    lines.  Use \code{line2d.reset()} to reset to the default options. 

    INPUT:

    - ``alpha`` -- How transparent the line is

    - ``thickness`` -- How thick the line is

    - ``rgbcolor`` -- The color as an RGB tuple

    - ``hue`` -- The color given as a hue

    - ``legend_label`` -- the label for this item in the legend

    Any MATPLOTLIB line option may also be passed in.  E.g.,

    - ``linestyle`` - The style of the line, which is one of
       - ``"-"`` (solid) -- default
       - ``"--"`` (dashed)
       - ``"-."`` (dash dot)
       - ``":"`` (dotted)
       - ``"None"`` or ``" "`` or ``""`` (nothing)

       The linestyle can also be prefixed with a drawing style (e.g., ``"steps--"``)

       - ``"default"`` (connect the points with straight lines)
       - ``"steps"`` or ``"steps-pre"`` (step function; horizontal
         line is to the left of point)
       - ``"steps-mid"`` (step function; points are in the middle of
         horizontal lines)
       - ``"steps-post"`` (step function; horizontal line is to the
         right of point)
        
    - ``marker``  - The style of the markers, which is one of
       - ``"None"`` or ``" "`` or ``""`` (nothing) -- default
       - ``","`` (pixel), ``"."`` (point)
       - ``"_"`` (horizontal line), ``"|"`` (vertical line)
       - ``"o"`` (circle), ``"p"`` (pentagon), ``"s"`` (square), ``"x"`` (x), ``"+"`` (plus), ``"*"`` (star)
       - ``"D"`` (diamond), ``"d"`` (thin diamond)
       - ``"H"`` (hexagon), ``"h"`` (alternative hexagon)
       - ``"<"`` (triangle left), ``">"`` (triangle right), ``"^"`` (triangle up), ``"v"`` (triangle down)
       - ``"1"`` (tri down), ``"2"`` (tri up), ``"3"`` (tri left), ``"4"`` (tri right)
       - ``0`` (tick left), ``1`` (tick right), ``2`` (tick up), ``3`` (tick down)
       - ``4`` (caret left), ``5`` (caret right), ``6`` (caret up), ``7`` (caret down)
       - ``"$...$"`` (math TeX string)

    - ``markersize`` -- the size of the marker in points

    - ``markeredgecolor`` -- the color of the marker edge

    - ``markerfacecolor`` -- the color of the marker face

    - ``markeredgewidth`` -- the size of the marker edge in points

    EXAMPLES:

    A blue conchoid of Nicomedes::
 
        sage: L = [[1+5*cos(pi/2+pi*i/100), tan(pi/2+pi*i/100)*(1+5*cos(pi/2+pi*i/100))] for i in range(1,100)]
        sage: line(L, rgbcolor=(1/4,1/8,3/4))

    A line with 2 complex points::

        sage: i = CC.0
        sage: line([1+i, 2+3*i])
 
    A blue hypotrochoid (3 leaves)::

        sage: n = 4; h = 3; b = 2
        sage: L = [[n*cos(pi*i/100)+h*cos((n/b)*pi*i/100),n*sin(pi*i/100)-h*sin((n/b)*pi*i/100)] for i in range(200)]
        sage: line(L, rgbcolor=(1/4,1/4,3/4))
 
    A blue hypotrochoid (4 leaves)::
 
        sage: n = 6; h = 5; b = 2
        sage: L = [[n*cos(pi*i/100)+h*cos((n/b)*pi*i/100),n*sin(pi*i/100)-h*sin((n/b)*pi*i/100)] for i in range(200)]
        sage: line(L, rgbcolor=(1/4,1/4,3/4))
 
    A red limacon of Pascal::
 
        sage: L = [[sin(pi*i/100)+sin(pi*i/50),-(1+cos(pi*i/100)+cos(pi*i/50))] for i in range(-100,101)]
        sage: line(L, rgbcolor=(1,1/4,1/2))
 
    A light green trisectrix of Maclaurin::
 
        sage: L = [[2*(1-4*cos(-pi/2+pi*i/100)^2),10*tan(-pi/2+pi*i/100)*(1-4*cos(-pi/2+pi*i/100)^2)] for i in range(1,100)]
        sage: line(L, rgbcolor=(1/4,1,1/8))
 
    A green lemniscate of Bernoulli::

        sage: cosines = [cos(-pi/2+pi*i/100) for i in range(201)]
        sage: v = [(1/c, tan(-pi/2+pi*i/100)) for i,c in enumerate(cosines) if c != 0]
        sage: L = [(a/(a^2+b^2), b/(a^2+b^2)) for a,b in v]
        sage: line(L, rgbcolor=(1/4,3/4,1/8))
 
    A red plot of the Jacobi elliptic function `\text{sn}(x,2)`, `-3 < x < 3`::
 
        sage: L = [(i/100.0, jacobi('sn', i/100.0 ,2.0)) for i in range(-300,300,30)]    
        sage: line(L, rgbcolor=(3/4,1/4,1/8))
        
    A red plot of `J`-Bessel function `J_2(x)`, `0 < x < 10`::

        sage: L = [(i/10.0, bessel_J(2,i/10.0)) for i in range(100)]
        sage: line(L, rgbcolor=(3/4,1/4,5/8))    
        
 
    A purple plot of the Riemann zeta function `\zeta(1/2 + it)`, `0 < t < 30`::

        sage: i = CDF.gen()
        sage: v = [zeta(0.5 + n/10 * i) for n in range(300)]
        sage: L = [(z.real(), z.imag()) for z in v]
        sage: line(L, rgbcolor=(3/4,1/2,5/8))
 
    A purple plot of the Hasse-Weil `L`-function `L(E, 1 + it)`, `-1 < t < 10`::

        sage: E = EllipticCurve('37a')
        sage: vals = E.lseries().values_along_line(1-I, 1+10*I, 100) # critical line
        sage: L = [(z[1].real(), z[1].imag()) for z in vals]
        sage: line(L, rgbcolor=(3/4,1/2,5/8))
 
    A red, blue, and green "cool cat"::

        sage: G = plot(-cos(x), -2, 2, thickness=5, rgbcolor=(0.5,1,0.5))
        sage: P = polygon([[1,2], [5,6], [5,0]], rgbcolor=(1,0,0))
        sage: Q = polygon([(-x,y) for x,y in P[0]], rgbcolor=(0,0,1))
        sage: G + P + Q   # show the plot

    A line with no points or one point::

        sage: line([])      #returns an empty plot
        sage: line([(1,1)])

    A line with a legend::

        sage: line([(0,0),(1,1)], legend_label='line')

    Extra options will get passed on to show(), as long as they are valid::
    
        sage: line([(0,1), (3,4)], figsize=[10, 2])
        sage: line([(0,1), (3,4)]).show(figsize=[10, 2]) # These are equivalent
    """
    from sage.plot.plot import Graphics, xydata_from_point_list
    if points == []:
        return Graphics()
    xdata, ydata = xydata_from_point_list(points)
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(Line(xdata, ydata, options))
    if options['legend_label']:
        g.legend(True)
    return g
Esempio n. 33
0
def region_plot(f, xrange, yrange, plot_points, incol, outcol, bordercol, borderstyle, borderwidth,**options):
    r"""
    ``region_plot`` takes a boolean function of two variables, `f(x,y)`
    and plots the region where f is True over the specified 
    ``xrange`` and ``yrange`` as demonstrated below.

    ``region_plot(f, (xmin, xmax), (ymin, ymax), ...)``

    INPUT:

    - ``f`` -- a boolean function of two variables

    - ``(xmin, xmax)`` -- 2-tuple, the range of ``x`` values OR 3-tuple
      ``(x,xmin,xmax)``

    - ``(ymin, ymax)`` -- 2-tuple, the range of ``y`` values OR 3-tuple
      ``(y,ymin,ymax)``

    - ``plot_points``  -- integer (default: 100); number of points to plot
      in each direction of the grid

    - ``incol`` -- a color (default: ``'blue'``), the color inside the region

    - ``outcol`` -- a color (default: ``'white'``), the color of the outside
      of the region

    If any of these options are specified, the border will be shown as indicated,
    otherwise it is only implicit (with color ``incol``) as the border of the 
    inside of the region.

     - ``bordercol`` -- a color (default: ``None``), the color of the border
       (``'black'`` if ``borderwidth`` or ``borderstyle`` is specified but not ``bordercol``)

    - ``borderstyle``  -- string (default: 'solid'), one of 'solid', 'dashed', 'dotted', 'dashdot'

    - ``borderwidth``  -- integer (default: None), the width of the border in pixels
 
    - ``legend_label`` -- the label for this item in the legend


    EXAMPLES:

    Here we plot a simple function of two variables::

        sage: x,y = var('x,y')
        sage: region_plot(cos(x^2+y^2) <= 0, (x, -3, 3), (y, -3, 3))
         
    Here we play with the colors::

        sage: region_plot(x^2+y^3 < 2, (x, -2, 2), (y, -2, 2), incol='lightblue', bordercol='gray')
        
    An even more complicated plot, with dashed borders::

        sage: region_plot(sin(x)*sin(y) >= 1/4, (x,-10,10), (y,-10,10), incol='yellow', bordercol='black', borderstyle='dashed', plot_points=250)

    A disk centered at the origin::

        sage: region_plot(x^2+y^2<1, (x,-1,1), (y,-1,1))

    A plot with more than one condition (all conditions must be true for the statement to be true)::

        sage: region_plot([x^2+y^2<1, x<y], (x,-2,2), (y,-2,2))

    Since it doesn't look very good, let's increase plot_points::

        sage: region_plot([x^2+y^2<1, x<y], (x,-2,2), (y,-2,2), plot_points=400)

    To get plots where only one condition needs to be true, use a function::

        sage: region_plot(lambda x,y: x^2+y^2<1 or x<y, (x,-2,2), (y,-2,2))
    
    The first quadrant of the unit circle::

        sage: region_plot([y>0, x>0, x^2+y^2<1], (x,-1.1, 1.1), (y,-1.1, 1.1), plot_points = 400)

    Here is another plot, with a huge border::

        sage: region_plot(x*(x-1)*(x+1)+y^2<0, (x, -3, 2), (y, -3, 3), incol='lightblue', bordercol='gray', borderwidth=10, plot_points=50)

    If we want to keep only the region where x is positive::

        sage: region_plot([x*(x-1)*(x+1)+y^2<0, x>-1], (x, -3, 2), (y, -3, 3), incol='lightblue', plot_points=50)

    Here we have a cut circle::

        sage: region_plot([x^2+y^2<4, x>-1], (x, -2, 2), (y, -2, 2), incol='lightblue', bordercol='gray', plot_points=200)

    The first variable range corresponds to the horizontal axis and
    the second variable range corresponds to the vertical axis::

        sage: s,t=var('s,t')
        sage: region_plot(s>0,(t,-2,2),(s,-2,2))

    ::

        sage: region_plot(s>0,(s,-2,2),(t,-2,2))

    """

    from sage.plot.plot import Graphics
    from sage.plot.misc import setup_for_eval_on_grid
    import numpy

    if not isinstance(f, (list, tuple)):
        f = [f]

    f = [equify(g) for g in f]

    g, ranges = setup_for_eval_on_grid(f, [xrange, yrange], plot_points)
    xrange,yrange=[r[:2] for r in ranges]

    xy_data_arrays = numpy.asarray([[[func(x, y) for x in xsrange(*ranges[0], include_endpoint=True)]
                                     for y in xsrange(*ranges[1], include_endpoint=True)]
                                    for func in g],dtype=float)
    xy_data_array=numpy.abs(xy_data_arrays.prod(axis=0))
    # Now we need to set entries to negative iff all
    # functions were negative at that point.
    neg_indices = (xy_data_arrays<0).all(axis=0)
    xy_data_array[neg_indices]=-xy_data_array[neg_indices]

    from matplotlib.colors import ListedColormap
    incol = rgbcolor(incol)
    outcol = rgbcolor(outcol)
    cmap = ListedColormap([incol, outcol])
    cmap.set_over(outcol)
    cmap.set_under(incol)
    
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore=['xmin', 'xmax']))
    g.add_primitive(ContourPlot(xy_data_array, xrange,yrange, 
                                dict(contours=[-1e307, 0, 1e307], cmap=cmap, fill=True, **options)))

    if bordercol or borderstyle or borderwidth:
        cmap = [rgbcolor(bordercol)] if bordercol else ['black']
        linestyles = [borderstyle] if borderstyle else None
        linewidths = [borderwidth] if borderwidth else None
        g.add_primitive(ContourPlot(xy_data_array, xrange, yrange, 
                                    dict(linestyles=linestyles, linewidths=linewidths,
                                         contours=[0], cmap=[bordercol], fill=False, **options)))
    
    return g
Esempio n. 34
0
def histogram(datalist, **options):
    """
    Computes and draws the histogram for list(s) of numerical data.
    See examples for the many options; even more customization is
    available using matplotlib directly.

    INPUT:

    - ``datalist`` -- A list, or a list of lists, of numerical data
    - ``align`` -- (default: "mid") How the bars align inside of each bin.
      Acceptable values are "left", "right" or "mid"
    - ``alpha`` -- (float in [0,1], default: 1) The transparency of the plot
    - ``bins`` -- The number of sections in which to divide the range. Also
      can be a sequence of points within the range that create the
      partition
    - ``color`` -- The color of the face of the bars or list of colors if
      multiple data sets are given
    - ``cumulative`` -- (boolean - default: False) If True, then
      a histogram is computed in which each bin gives the counts in that
      bin plus all bins for smaller values.  Negative values give
      a reversed direction of accumulation
    - ``edgecolor`` -- The color of the the border of each bar
    - ``fill`` -- (boolean - default: True) Whether to fill the bars
    - ``hatch`` -- (default: None) symbol to fill the bars with - one of
      "/", "\\", "|", "-", "+", "x", "o", "O", ".", "*", "" (or None)
    - ``hue`` -- The color of the bars given as a hue. See
      :mod:`~sage.plot.colors.hue` for more information on the hue
    - ``label`` -- A string label for each data list given
    - ``linewidth`` -- (float) width of the lines defining the bars
    - ``linestyle`` -- (default: 'solid') Style of the line. One of 'solid'
      or '-', 'dashed' or '--', 'dotted' or ':', 'dashdot' or '-.'
    - ``normed`` -- (boolean - default: False) If True, the counts are
      normalized to form a probability density.
    - ``range`` -- A list [min, max] which define the range of the
      histogram. Values outside of this range are treated as outliers and
      omitted from counts
    - ``rwidth`` -- (float in [0,1], default: 1) The relative width of the bars
      as a fraction of the bin width
    - ``stacked`` -- (boolean - default: False) If True, multiple data are
      stacked on top of each other
    - ``weights`` -- (list) A sequence of weights the same length as the data
      list. If supplied, then each value contributes its associated weight
      to the bin count
    - ``zorder`` -- (integer) the layer level at which to draw the histogram

    .. NOTE::

        The ``weights`` option works only with a single list. List of lists
        representing multiple data are not supported.

    EXAMPLES:

    A very basic histogram for four data points::

        sage: histogram([1,2,3,4], bins=2)
        Graphics object consisting of 1 graphics primitive

    We can see how the histogram compares to various distributions.
    Note the use of the ``normed`` keyword to guarantee the plot
    looks like the probability density function::

        sage: nv = normalvariate
        sage: H = histogram([nv(0,1) for _ in range(1000)], bins=20, normed=True, range=[-5,5])
        sage: P = plot( 1/sqrt(2*pi)*e^(-x^2/2), (x,-5,5), color='red', linestyle='--')
        sage: H+P
        Graphics object consisting of 2 graphics primitives

    There are many options one can use with histograms.  Some of these
    control the presentation of the data, even if it is boring::

        sage: histogram(list(range(100)), color=(1,0,0), label='mydata',\
              rwidth=.5, align="right")
        Graphics object consisting of 1 graphics primitive

    This includes many usual matplotlib styling options::

        sage: T = RealDistribution('lognormal', [0,1])
        sage: histogram( [T.get_random_element() for _ in range(100)], alpha=0.3,\
              edgecolor='red', fill=False, linestyle='dashed', hatch='O', linewidth=5)
        Graphics object consisting of 1 graphics primitive
        sage: histogram( [T.get_random_element() for _ in range(100)],linestyle='-.')
        Graphics object consisting of 1 graphics primitive

    We can do several data sets at once if desired::

        sage: histogram([srange(0,1,.1)*10, [nv(0, 1) for _ in range(100)]], color=['red','green'], bins=5)
        Graphics object consisting of 1 graphics primitive

    We have the option of stacking the data sets too::

        sage: histogram([ [1,1,1,1,2,2,2,3,3,3], [4,4,4,4,3,3,3,2,2,2] ], stacked=True, color=['blue', 'red'])
        Graphics object consisting of 1 graphics primitive

    It is possible to use weights with the histogram as well::

        sage: histogram(list(range(10)), bins=3, weights=[1,2,3,4,5,5,4,3,2,1])
        Graphics object consisting of 1 graphics primitive
    """
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(Histogram(datalist, options=options))
    return g
Esempio n. 35
0
def contour_plot(f, xrange, yrange, **options):
    r"""    
    ``contour_plot`` takes a function of two variables, `f(x,y)`
    and plots contour lines of the function over the specified 
    ``xrange`` and ``yrange`` as demonstrated below.

    ``contour_plot(f, (xmin, xmax), (ymin, ymax), ...)``

    INPUT:

    - ``f`` -- a function of two variables

    - ``(xmin, xmax)`` -- 2-tuple, the range of ``x`` values OR 3-tuple
      ``(x,xmin,xmax)``

    - ``(ymin, ymax)`` -- 2-tuple, the range of ``y`` values OR 3-tuple
      ``(y,ymin,ymax)``

    The following inputs must all be passed in as named parameters:

    - ``plot_points``  -- integer (default: 100); number of points to plot
      in each direction of the grid.  For old computers, 25 is fine, but 
      should not be used to verify specific intersection points.

    - ``fill`` -- bool (default: ``True``), whether to color in the area
      between contour lines

    - ``cmap`` -- a colormap (default: ``'gray'``), the name of
      a predefined colormap, a list of colors or an instance of a matplotlib
      Colormap. Type: ``import matplotlib.cm; matplotlib.cm.datad.keys()``
      for available colormap names.

    - ``contours`` -- integer or list of numbers (default: ``None``):
      If a list of numbers is given, then this specifies the contour levels
      to use.  If an integer is given, then this many contour lines are
      used, but the exact levels are determined automatically. If ``None``
      is passed (or the option is not given), then the number of contour
      lines is determined automatically, and is usually about 5.

    - ``linewidths`` -- integer or list of integer (default: None), if
      a single integer all levels will be of the width given,
      otherwise the levels will be plotted with the width in the order
      given.  If the list is shorter than the number of contours, then
      the widths will be repeated cyclically.

    - ``linestyles`` -- string or list of strings (default: None), the
      style of the lines to be plotted, one of: solid, dashed,
      dashdot, or dotted.  If the list is shorter than the number of
      contours, then the styles will be repeated cyclically.

    - ``labels`` -- boolean (default: False) Show level labels or not.
 
      The following options are to adjust the style and placement of
      labels, they have no effect if no labels are shown.

      - ``label_fontsize`` -- integer (default: 9), the font size of the labels.

      - ``label_colors`` -- string or sequence of colors (default:
        None) If a string, gives the name of a single color with which
        to draw all labels.  If a sequence, gives the colors of the
        labels.  A color is a string giving the name of one or a
        3-tuple of floats.

      - ``label_inline`` -- boolean (default: False if fill is True,
        otherwise True), controls whether the underlying contour is
        removed or not.

      - ``label_inline_spacing`` -- integer (default: 3), When inline,
        this is the amount of contour that is removed from each side,
        in pixels.

      - ``label_fmt`` -- a format string (default: "%1.2f"), this is
        used to get the label text from the level.  This can also be a
        dictionary with the contour levels as keys and corresponding
        text string labels as values.  It can also be any callable which
        returns a string when called with a numeric contour level.

    - ``colorbar`` -- boolean (default: False) Show a colorbar or not.
    
      The following options are to adjust the style and placement of
      colorbars.  They have no effect if a colorbar is not shown.

      - ``colorbar_orientation`` -- string (default: 'vertical'),
        controls placement of the colorbar, can be either 'vertical'
        or 'horizontal'

      - ``colorbar_format`` -- a format string, this is used to format
        the colorbar labels.

      - ``colorbar_spacing`` -- string (default: 'proportional').  If
        'proportional', make the contour divisions proportional to
        values.  If 'uniform', space the colorbar divisions uniformly,
        without regard for numeric values.

    - ``legend_label`` -- the label for this item in the legend

    EXAMPLES:

    Here we plot a simple function of two variables.  Note that
    since the input function is an expression, we need to explicitly
    declare the variables in 3-tuples for the range::

        sage: x,y = var('x,y')
        sage: contour_plot(cos(x^2+y^2), (x, -4, 4), (y, -4, 4))
         
    Here we change the ranges and add some options::

        sage: x,y = var('x,y')
        sage: contour_plot((x^2)*cos(x*y), (x, -10, 5), (y, -5, 5), fill=False, plot_points=150)
        
    An even more complicated plot::

        sage: x,y = var('x,y')
        sage: contour_plot(sin(x^2 + y^2)*cos(x)*sin(y), (x, -4, 4), (y, -4, 4),plot_points=150)

    Some elliptic curves, but with symbolic endpoints.  In the first
    example, the plot is rotated 90 degrees because we switch the
    variables `x`, `y`::

        sage: x,y = var('x,y')
        sage: contour_plot(y^2 + 1 - x^3 - x, (y,-pi,pi), (x,-pi,pi))

    ::

        sage: contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi))

    We can play with the contour levels::

        sage: x,y = var('x,y')
        sage: f(x,y) = x^2 + y^2
        sage: contour_plot(f, (-2, 2), (-2, 2))

    ::

        sage: contour_plot(f, (-2, 2), (-2, 2), contours=2, cmap=[(1,0,0), (0,1,0), (0,0,1)])
 
    ::

        sage: contour_plot(f, (-2, 2), (-2, 2), contours=(0.1, 1.0, 1.2, 1.4), cmap='hsv')

    ::

        sage: contour_plot(f, (-2, 2), (-2, 2), contours=(1.0,), fill=False)

    ::

        sage: contour_plot(x-y^2,(x,-5,5),(y,-3,3),contours=[-4,0,1])

    We can change the style of the lines::

        sage: contour_plot(f, (-2,2), (-2,2), fill=False, linewidths=10)

    ::

        sage: contour_plot(f, (-2,2), (-2,2), fill=False, linestyles='dashdot')

    ::

        sage: P=contour_plot(x^2-y^2,(x,-3,3),(y,-3,3),contours=[0,1,2,3,4],\
        ...    linewidths=[1,5],linestyles=['solid','dashed'],fill=False)
        sage: P

    ::

        sage: P=contour_plot(x^2-y^2,(x,-3,3),(y,-3,3),contours=[0,1,2,3,4],\
        ...    linewidths=[1,5],linestyles=['solid','dashed'])
        sage: P

    We can add labels and play with them::

        sage: contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi),  fill=False, cmap='hsv', labels=True)

    ::

        sage: P=contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), fill=False, cmap='hsv',\
        ...     labels=True, label_fmt="%1.0f", label_colors='black')
        sage: P

    ::

        sage: P=contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), fill=False, cmap='hsv',labels=True,\
        ...    contours=[-4,0,4],  label_fmt={-4:"low", 0:"medium", 4: "hi"}, label_colors='black')
        sage: P

    ::

        sage: P=contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), fill=False, cmap='hsv',labels=True,\
        ...    contours=[-4,0,4],  label_fmt=lambda x: "$z=%s$"%x, label_colors='black', label_inline=True, \
        ...    label_fontsize=12)
        sage: P

    ::

        sage: P=contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), \
        ...    fill=False, cmap='hsv', labels=True, label_fontsize=18)
        sage: P

    ::

        sage: P=contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), \
        ...    fill=False, cmap='hsv', labels=True, label_inline_spacing=1)
        sage: P

    ::

        sage: P= contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi), \
        ...    fill=False, cmap='hsv', labels=True, label_inline=False)
        sage: P
    
    We can change the color of the labels if so desired::

        sage: contour_plot(f, (-2,2), (-2,2), labels=True, label_colors='red')

    We can add a colorbar as well::

        sage: f(x,y)=x^2-y^2
        sage: contour_plot(f, (x,-3,3), (y,-3,3), colorbar=True)

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), colorbar=True,colorbar_orientation='horizontal')

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), contours=[-2,-1,4],colorbar=True)

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), contours=[-2,-1,4],colorbar=True,colorbar_spacing='uniform')

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), contours=[0,2,3,6],colorbar=True,colorbar_format='%.3f')

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), labels=True,label_colors='red',contours=[0,2,3,6],colorbar=True)

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), cmap='winter', contours=20, fill=False, colorbar=True)

    This should plot concentric circles centered at the origin::

        sage: x,y = var('x,y')
        sage: contour_plot(x^2+y^2-2,(x,-1,1), (y,-1,1))

    Extra options will get passed on to show(), as long as they are valid::

        sage: f(x, y) = cos(x) + sin(y)
        sage: contour_plot(f, (0, pi), (0, pi), axes=True)

    ::

        sage: contour_plot(f, (0, pi), (0, pi)).show(axes=True) # These are equivalent

    Note that with ``fill=False`` and grayscale contours, there is the 
    possibility of confusion between the contours and the axes, so use
    ``fill=False`` together with ``axes=True`` with caution::

        sage: contour_plot(f, (-pi, pi), (-pi, pi), fill=False, axes=True) 

    TESTS:

    To check that ticket 5221 is fixed, note that this has three curves, not two::

        sage: x,y = var('x,y')
        sage: contour_plot(x-y^2,(x,-5,5),(y,-3,3),contours=[-4,-2,0], fill=False)
    """
    from sage.plot.plot import Graphics
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid([f], [xrange, yrange], options['plot_points'])
    g = g[0]
    xrange,yrange=[r[:2] for r in ranges]
    
    xy_data_array = [[g(x, y) for x in xsrange(*ranges[0], include_endpoint=True)]
                              for y in xsrange(*ranges[1], include_endpoint=True)]

    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore=['xmin', 'xmax']))
    g.add_primitive(ContourPlot(xy_data_array, xrange, yrange, options))
    return g        
Esempio n. 36
0
File: braid.py Progetto: chos9/sage
    def plot(self, color='blue', orientation='bottom-top', gap=0.05, aspect_ratio=1, axes=False, **kwds):
        """
        Plot the braid

        The following options are available:

        - ``orientation`` - (default: ``'bottom-top'``) determines how
          the braid is printed. The possible values are:

            * ``'bottom-top'``, the braid is printed from bottom to top

            * ``'top-bottom'``, the braid is printed from top to bottom

            * ``'left-right'``, the braid is printed from left to right

        - ``gap`` -- floating point number (default: 0.05). determines
          the size of the gap left when a strand goes under another.

        - ``aspect_ratio`` -- floating point number (default:
          ``1``). The aspect ratio.

        - ``**kwds`` -- other keyword options that are passed to
          :meth:`~sage.plot.bezier_path` and :meth:`~sage.plot.line`.

        EXAMPLES::

            sage: B = BraidGroup(4, 's')
            sage: b = B([1, 2, 3, 1, 2, 1])
            sage: b.plot()
        """
        from sage.plot.bezier_path import bezier_path
        from sage.plot.plot import Graphics, line
        if orientation=='top-bottom':
            orx = 0
            ory = -1
            nx = 1
            ny = 0
        elif orientation=='left-right':
            orx = 1
            ory = 0
            nx = 0
            ny = -1
        elif orientation=='bottom-top':
            orx = 0
            ory = 1
            nx = 1
            ny = 0
        else:
            raise ValueError('unknown value for "orientation"')
        col = color
        br = self.Tietze()
        n = self.strands()
        a = Graphics()
        op = gap
        for i in range(len(br)):
            m = br[i]
            for j in range(n):
                if m==j+1:
                    a += bezier_path([[(j*nx+i*orx, i*ory+j*ny), (j*nx+orx*(i+0.25), j*ny+ory*(i+0.25)),
                                       (nx*(j+0.5)+orx*(i+0.5), ny*(j+0.5)+ory*(i+0.5))],
                                      [(nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)),
                                       (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col, **kwds)
                elif m==j:
                    a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)),
                                       (nx*(j-0.5+4*op)+orx*(i+0.5-2*op), ny*(j-0.5+4*op)+ory*(i+0.5-2*op)),
                                       (nx*(j-0.5+2*op)+orx*(i+0.5-op), ny*(j-0.5+2*op)+ory*(i+0.5-op))]],
                                     color=col, **kwds)
                    a += bezier_path([[(nx*(j-0.5-2*op)+orx*(i+0.5+op), ny*(j-0.5-2*op)+ory*(i+0.5+op)),
                                       (nx*(j-0.5-4*op)+orx*(i+0.5+2*op), ny*(j-0.5-4*op)+ory*(i+0.5+2*op)),
                                       (nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)),
                                       (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col, **kwds)
                elif -m==j+1:
                    a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)),
                                       (nx*(j+0.5-4*op)+orx*(i+0.5-2*op), ny*(j+0.5-4*op)+ory*(i+0.5-2*op)),
                                       (nx*(j+0.5-2*op)+orx*(i+0.5-op), ny*(j+0.5-2*op)+ory*(i+0.5-op))]],
                                     color=col, **kwds)
                    a += bezier_path([[(nx*(j+0.5+2*op)+orx*(i+0.5+op), ny*(j+0.5+2*op)+ory*(i+0.5+op)),
                                       (nx*(j+0.5+4*op)+orx*(i+0.5+2*op), ny*(j+0.5+4*op)+ory*(i+0.5+2*op)),
                                       (nx*(j+1)+orx*(i+0.75), ny*(j+1)+ory*(i+0.75)),
                                       (nx*(j+1)+orx*(i+1), ny*(j+1)+ory*(i+1))]], color=col, **kwds)
                elif -m==j:
                    a += bezier_path([[(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+0.25), ny*j+ory*(i+0.25)),
                                       (nx*(j-0.5)+orx*(i+0.5), ny*(j-0.5)+ory*(i+0.5))],
                                      [(nx*(j-1)+orx*(i+0.75), ny*(j-1)+ory*(i+0.75)),
                                       (nx*(j-1)+orx*(i+1), ny*(j-1)+ory*(i+1))]], color=col, **kwds)
                else:
                    a += line([(nx*j+orx*i, ny*j+ory*i), (nx*j+orx*(i+1), ny*j+ory*(i+1))], color=col, **kwds)
        a.set_aspect_ratio(aspect_ratio)
        a.axes(axes)
        return a
Esempio n. 37
0
def arrow2d(tailpoint=None, headpoint=None, path=None, **options):
    """
    If tailpoint and headpoint are provided, returns an arrow from (xmin, ymin) 
    to (xmax, ymax).  If tailpoint or headpoint is None and path is not None,
    returns an arrow along the path.  (See further info on paths in bezier_path).

    INPUT:

    - ``tailpoint`` - the starting point of the arrow

    - ``headpoint`` - where the arrow is pointing to

    - ``path`` - the list of points and control points (see bezier_path for detail) that 
      the arrow will follow from source to destination

    - ``head`` - 0, 1 or 2, whether to draw the head at the start (0), end (1) or both (2)
      of the path (using 0 will swap headpoint and tailpoint).  This is ignored
      in 3D plotting.

    - ``width`` - (default: 2) the width of the arrow shaft, in points

    - ``color`` - (default: (0,0,1)) the color of the arrow (as an RGB tuple or a string)

    - ``hue`` - the color of the arrow (as a number)

    - ``arrowsize`` - the size of the arrowhead

    - ``arrowshorten`` - the length in points to shorten the arrow (ignored if using path
      parameter)

    - ``legend_label`` - the label for this item in the legend 

    - ``zorder`` - the layer level to draw the arrow-- note that this is ignored in 3D
      plotting.

    EXAMPLES:

    A straight, blue arrow::

       sage: arrow2d((1, 1), (3, 3))
    
    Make a red arrow::

       sage: arrow2d((-1, -1), (2, 3), color=(1,0,0))
       sage: arrow2d((-1, -1), (2, 3), color='red')

    You can change the width of an arrow::

        sage: arrow2d((1, 1), (3, 3), width=5, arrowsize=15)

    A pretty circle of arrows::

        sage: sum([arrow2d((0,0), (cos(x),sin(x)), hue=x/(2*pi)) for x in [0..2*pi,step=0.1]])

    If we want to draw the arrow between objects, for example, the
    boundaries of two lines, we can use the arrowshorten option
    to make the arrow shorter by a certain number of points::

        sage: line([(0,0),(1,0)],thickness=10)+line([(0,1),(1,1)], thickness=10)+arrow2d((0.5,0),(0.5,1), arrowshorten=10,rgbcolor=(1,0,0))

    If BOTH headpoint and tailpoint are None, then an empty plot is returned::
    
        sage: arrow2d(headpoint=None, tailpoint=None)
        
    
    We can also draw an arrow with a legend::

        sage: arrow((0,0), (0,2), legend_label='up')

    Extra options will get passed on to show(), as long as they are valid::
 
        sage: arrow2d((-2, 2), (7,1), frame=True)
        sage: arrow2d((-2, 2), (7,1)).show(frame=True)
    """
    from sage.plot.plot import Graphics
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    if headpoint is not None and tailpoint is not None:
        xtail, ytail = tailpoint
        xhead, yhead = headpoint
        g.add_primitive(Arrow(xtail, ytail, xhead, yhead, options=options))
    elif path is not None:
        g.add_primitive(CurveArrow(path, options=options))
    elif tailpoint is None and headpoint is None:
        return g
    else:
        raise TypeError('Arrow requires either both headpoint and tailpoint or a path parameter.')
    if options['legend_label']:
        g.legend(True)
    return g
Esempio n. 38
0
def _draw_funddom(coset_reps, format="S"):
    r""" Draw a fundamental domain for G.

    INPUT:

    - ``format``  -- (default 'Disp') How to present the f.d.
    -   ``S`` -- Display directly on the screen

    EXAMPLES::


    sage: G=MySubgroup(Gamma0(3))
    sage: G._draw_funddom()

    """
    pi = RR.pi()
    pi_3 = pi / RR(3.0)
    from sage.plot.plot import (Graphics, line)
    from sage.functions.trig import (cos, sin)
    g = Graphics()
    x1 = RR(-0.5)
    y1 = RR(sqrt(3) / 2)
    x2 = RR(0.5)
    y2 = RR(sqrt(3) / 2)
    xmax = RR(20.0)
    l1 = line([[x1, y1], [x1, xmax]])
    l2 = line([[x2, y2], [x2, xmax]])
    l3 = line([[x2, xmax], [x1,
                            xmax]])  # This is added to make a closed contour
    c0 = _circ_arc(RR(pi / 3.0), RR(2.0 * pi) / RR(3.0), 0, 1, 100)
    tri = c0 + l1 + l3 + l2
    g = g + tri
    for A in coset_reps:
        [a, b, c, d] = A
        if (a == 1 and b == 0 and c == 0 and d == 1):
            continue
        if (a < 0):
            a = RR(-a)
            b = RR(-b)
            c = RR(-c)
            d = RR(-d)
        else:
            a = RR(a)
            b = RR(b)
            c = RR(c)
            d = RR(d)
        if (c == 0):  # then this is easier
            L0 = [[cos(pi_3 * RR(i / 100.0)) + b,
                   sin(pi_3 * RR(i / 100.0))] for i in range(100, 201)]
            L1 = [[x1 + b, y1], [x1 + b, xmax]]
            L2 = [[x2 + b, y2], [x2 + b, xmax]]
            L3 = [[x2 + b, xmax], [x1 + b, xmax]]
            c0 = line(L0)
            l1 = line(L1)
            l2 = line(L2)
            l3 = line(L3)
            tri = c0 + l1 + l3 + l2
            g = g + tri
        else:
            den = (c * x1 + d)**2 + c**2 * y1**2
            x1_t = (a * c * (x1**2 + y1**2) +
                    (a * d + b * c) * x1 + b * d) / den
            y1_t = y1 / den
            den = (c * x2 + d)**2 + c**2 * y2**2
            x2_t = (a * c * (x2**2 + y2**2) +
                    (a * d + b * c) * x2 + b * d) / den
            y2_t = y2 / den
            inf_t = a / c
            c0 = _geodesic_between_two_points(x1_t, y1_t, x2_t, y2_t)
            c1 = _geodesic_between_two_points(x1_t, y1_t, inf_t, 0.)
            c2 = _geodesic_between_two_points(x2_t, y2_t, inf_t, 0.0)
            tri = c0 + c1 + c2
            g = g + tri
    return g
Esempio n. 39
0
def _draw_funddom_d(coset_reps,format="MP",z0=I):
    r""" Draw a fundamental domain for self in the circle model
    INPUT:
    - ''format''  -- (default 'Disp') How to present the f.d.
    =  'S'  -- Display directly on the screen
    - z0          -- (default I) the upper-half plane is mapped to the disk by z-->(z-z0)/(z-z0.conjugate())
    EXAMPLES::
        

    sage: G=MySubgroup(Gamma0(3))
    sage: G._draw_funddom_d()
        
    """
    # The fundamental domain consists of copies of the standard fundamental domain
    pi=RR.pi()
    from sage.plot.plot import (Graphics,line)
    g=Graphics()
    bdcirc=_circ_arc(0 ,2 *pi,0 ,1 ,1000 )
    g=g+bdcirc
    # Corners
    x1=-RR(0.5) ; y1=RR(sqrt(3 )/2)
    x2=RR(0.5) ; y2=RR(sqrt(3 )/2)
    z_inf=1 
    l1 = _geodesic_between_two_points_d(x1,y1,x1,infinity)
    l2 = _geodesic_between_two_points_d(x2,y2,x2,infinity)
    c0 = _geodesic_between_two_points_d(x1,y1,x2,y2)
    tri=c0+l1+l2
    g=g+tri
    for A in coset_reps:
        [a,b,c,d]=A
        if(a==1  and b==0  and c==0  and d==1 ):
            continue
        if(a<0 ):
            a=-a; b=-b; c=-c; d=-1 
        if(c==0 ): # then this is easier
            l1 = _geodesic_between_two_points_d(x1+b,y1,x1+b,infinity)
            l2 = _geodesic_between_two_points_d(x2+b,y2,x2+b,infinity)
            c0 = _geodesic_between_two_points_d(x1+b,y1,x2+b,y2)
            # c0=line(L0); l1=line(L1); l2=line(L2); l3=line(L3)
            tri=c0+l1+l2
            g=g+tri
        else:
            den=(c*x1+d)**2 +c**2 *y1**2 
            x1_t=(a*c*(x1**2 +y1**2 )+(a*d+b*c)*x1+b*d)/den
            y1_t=y1/den
            den=(c*x2+d)**2 +c**2 *y2**2 
            x2_t=(a*c*(x2**2 +y2**2 )+(a*d+b*c)*x2+b*d)/den
            y2_t=y2/den
            inf_t=a/c
            c0=_geodesic_between_two_points_d(x1_t,y1_t,x2_t,y2_t)
            c1=_geodesic_between_two_points_d(x1_t,y1_t,inf_t,0.0 )
            c2=_geodesic_between_two_points_d(x2_t,y2_t,inf_t,0.0 )
            tri=c0+c1+c2
            g=g+tri
    g.xmax(1 )
    g.ymax(1 )
    g.xmin(-1 )
    g.ymin(-1 )
    g.set_aspect_ratio(1 )
    return g
Esempio n. 40
0
    from sage.plot.misc import setup_for_eval_on_grid
    z, ranges = setup_for_eval_on_grid([f,g], [xrange, yrange], options['plot_points'])
    f,g = z

    xpos_array, ypos_array, xvec_array, yvec_array = [],[],[],[]
    for x in xsrange(*ranges[0], include_endpoint=True):
        for y in xsrange(*ranges[1], include_endpoint=True):
            xpos_array.append(x)
            ypos_array.append(y)
            xvec_array.append(f(x,y))
            yvec_array.append(g(x,y))

    import numpy
    xvec_array = numpy.ma.masked_invalid(numpy.array(xvec_array, dtype=float))
    yvec_array = numpy.ma.masked_invalid(numpy.array(yvec_array, dtype=float))
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(PlotField(xpos_array, ypos_array, xvec_array, yvec_array, options))
    return g

def plot_slope_field(f, xrange, yrange, **kwds):
    r"""
    ``plot_slope_field`` takes a function of two variables xvar and yvar
    (for instance, if the variables are `x` and `y`, take `f(x,y)`), and at
    representative points `(x_i,y_i)` between xmin, xmax, and ymin, ymax
    respectively, plots a line with slope `f(x_i,y_i)` (see below).

    ``plot_slope_field(f, (xvar, xmin, xmax), (yvar, ymin, ymax))``

    EXAMPLES: 
Esempio n. 41
0
def text(string, xy, **options):
    r"""
    Returns a 2D text graphics object at the point `(x,y)`.
    
    Type ``text.options`` for a dictionary of options for 2D text.

    2D OPTIONS:

    - ``fontsize`` - How big the text is

    - ``rgbcolor`` - The color as an RGB tuple

    - ``hue`` - The color given as a hue

    - ``rotation`` - How to rotate the text: angle in degrees, vertical, horizontal

    - ``vertical_alignment`` - How to align vertically: top, center, bottom

    - ``horizontal_alignment`` - How to align horizontally: left, center, right

    - ``axis_coords`` - (default: False) if True, use axis coordinates, so that
      (0,0) is the lower left and (1,1) upper right, regardless of the x and y
      range of plotted values. 

    EXAMPLES::

        sage: text("Sage is really neat!!",(2,12))

    The same text in larger font and colored red::

        sage: text("Sage is really neat!!",(2,12),fontsize=20,rgbcolor=(1,0,0))

    Same text but guaranteed to be in the lower left no matter what::

        sage: text("Sage is really neat!!",(0,0), axis_coords=True, horizontal_alignment='left')

    Same text rotated around the left, bottom corner of the text::

        sage: text("Sage is really neat!!",(0,0), rotation=45.0, horizontal_alignment='left', vertical_alignment='bottom')

    Same text oriented vertically::

        sage: text("Sage is really neat!!",(0,0), rotation="vertical")

    You can also align text differently::

        sage: t1 = text("Hello",(1,1), vertical_alignment="top")
        sage: t2 = text("World", (1,0.5), horizontal_alignment="left")
        sage: t1 + t2   # render the sum

    You can save text as part of PDF output::

        sage: text("sage", (0,0), rgbcolor=(0,0,0)).save(SAGE_TMP + 'a.pdf')

    Text must be 2D (use the text3d command for 3D text)::

        sage: t = text("hi",(1,2,3))
        Traceback (most recent call last):
        ...
        ValueError: use text3d instead for text in 3d
        sage: t = text3d("hi",(1,2,3))

    Extra options will get passed on to show(), as long as they are valid::
    
        sage: text("MATH IS AWESOME", (0, 0), fontsize=40, axes=False)
        sage: text("MATH IS AWESOME", (0, 0), fontsize=40).show(axes=False) # These are equivalent
    """
    try:
        x, y = xy
    except ValueError:
        if isinstance(xy, (list, tuple)) and len(xy) == 3:
            raise ValueError, "use text3d instead for text in 3d"
        raise
    from sage.plot.plot import Graphics
    options['rgbcolor'] = to_mpl_color(options['rgbcolor'])
    point = (float(x), float(y))
    g = Graphics()
    g._set_extra_kwds(
        Graphics._extract_kwds_for_show(options, ignore='fontsize'))
    g.add_primitive(Text(string, point, options))
    return g
Esempio n. 42
0
def matrix_plot(mat, **options):
    r"""
    A plot of a given matrix or 2D array.
    
    If the matrix is dense, each matrix element is given a different
    color value depending on its relative size compared to the other
    elements in the matrix.  If the matrix is sparse, colors only
    indicate whether an element is nonzero or zero, so the plot
    represents the sparsity pattern of the matrix.

    The tick marks drawn on the frame axes denote the row numbers
    (vertical ticks) and the column numbers (horizontal ticks) of the
    matrix.

    INPUT:

    - ``mat`` - a 2D matrix or array

    The following input must all be passed in as named parameters, if
    default not used:

    - ``cmap`` - a colormap (default: 'gray'), the name of
      a predefined colormap, a list of colors,
      or an instance of a matplotlib Colormap.
      Type: ``import matplotlib.cm; matplotlib.cm.datad.keys()``
      for available colormap names.

    - ``colorbar`` -- boolean (default: False) Show a colorbar or not (dense matrices only).
    
      The following options are used to adjust the style and placement
      of colorbars.  They have no effect if a colorbar is not shown.

      - ``colorbar_orientation`` -- string (default: 'vertical'),
        controls placement of the colorbar, can be either 'vertical'
        or 'horizontal'

      - ``colorbar_format`` -- a format string, this is used to format
        the colorbar labels.

      - ``colorbar_options`` -- a dictionary of options for the matplotlib
        colorbar API.  Documentation for the :mod:`matplotlib.colorbar` module
        has details.

    - ``norm`` - If None (default), the value range is scaled to the interval
      [0,1].  If 'value', then the actual value is used with no
      scaling.  A :class:`matplotlib.colors.Normalize` instance may
      also passed.

    - ``vmin`` - The minimum value (values below this are set to this value)

    - ``vmax`` - The maximum value (values above this are set to this value)

    - ``origin`` - If 'upper' (default), the first row of the matrix
      is on the top of the graph.  If 'lower', the first row is on the
      bottom of the graph.

    - ``subdivisions`` - If True, plot the subdivisions of the matrix as lines.

    - ``subdivision_boundaries`` - a list of lists in the form
      ``[row_subdivisions, column_subdivisions]``, which specifies
      the row and column subdivisions to use.  If not specified,
      defaults to the matrix subdivisions
    
    - ``subdivision_style`` - a dictionary of properties passed
      on to the :func:`~sage.plot.line.line2d` command for plotting
      subdivisions.  If this is a two-element list or tuple, then it 
      specifies the styles of row and column divisions, respectively.

    EXAMPLES:
    
    A matrix over `\ZZ` colored with different grey levels::
    
        sage: matrix_plot(matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]]))

    Here we make a random matrix over `\RR` and use ``cmap='hsv'``
    to color the matrix elements different RGB colors::

        sage: matrix_plot(random_matrix(RDF, 50), cmap='hsv')

    By default, entries are scaled to the interval [0,1] before
    determining colors from the color map.  That means the two plots
    below are the same::

        sage: P = matrix_plot(matrix(2,[1,1,3,3]))
        sage: Q = matrix_plot(matrix(2,[2,2,3,3]))
        sage: P; Q

    However, we can specify which values scale to 0 or 1 with the
    ``vmin`` and ``vmax`` parameters (values outside the range are
    clipped).  The two plots below are now distinguished::

        sage: P = matrix_plot(matrix(2,[1,1,3,3]), vmin=0, vmax=3, colorbar=True)
        sage: Q = matrix_plot(matrix(2,[2,2,3,3]), vmin=0, vmax=3, colorbar=True)
        sage: P; Q

    We can also specify a norm function of 'value', which means that
    there is no scaling performed::
    
        sage: matrix_plot(random_matrix(ZZ,10)*.05, norm='value', colorbar=True)

    Matrix subdivisions can be plotted as well::
    
        sage: m=random_matrix(RR,10)
        sage: m.subdivide([2,4],[6,8])
        sage: matrix_plot(m, subdivisions=True, subdivision_style=dict(color='red',thickness=3))
    
    You can also specify your own subdivisions and separate styles
    for row or column subdivisions::
    
        sage: m=random_matrix(RR,10)
        sage: matrix_plot(m, subdivisions=True, subdivision_boundaries=[[2,4],[6,8]], subdivision_style=[dict(color='red',thickness=3),dict(linestyle='--',thickness=6)])

    Generally matrices are plotted with the (0,0) entry in the upper
    left.  However, sometimes if we are plotting an image, we'd like
    the (0,0) entry to be in the lower left.  We can do that with the
    ``origin`` argument::

        sage: matrix_plot(identity_matrix(100), origin='lower')

    Another random plot, but over `\GF{389}`::

        sage: m = random_matrix(GF(389), 10)
        sage: matrix_plot(m, cmap='Oranges')

    It also works if you lift it to the polynomial ring::

        sage: matrix_plot(m.change_ring(GF(389)['x']), cmap='Oranges')

    We have several options for colorbars::

        sage: matrix_plot(random_matrix(RDF, 50), colorbar=True, colorbar_orientation='horizontal')

    ::

        sage: matrix_plot(random_matrix(RDF, 50), colorbar=True, colorbar_format='%.3f')

    The length of a color bar and the length of the adjacent
    matrix plot dimension may be quite different.  This example
    shows how to adjust the length of the colorbar by passing a
    dictionary of options to the matplotlib colorbar routines.  ::

        sage: m = random_matrix(ZZ, 40, 80, x=-10, y=10)
        sage: m.plot(colorbar=True, colorbar_orientation='vertical',
        ...          colorbar_options={'shrink':0.50})

    Here we plot a random sparse matrix::

        sage: sparse = matrix(dict([((randint(0, 10), randint(0, 10)), 1) for i in xrange(100)]))
        sage: matrix_plot(sparse)

    ::

        sage: A=random_matrix(ZZ,100000,density=.00001,sparse=True)
        sage: matrix_plot(A,marker=',')

    As with dense matrices, sparse matrix entries are automatically
    converted to floating point numbers before plotting.  Thus the
    following works::

        sage: b=random_matrix(GF(2),200,sparse=True,density=0.01)
        sage: matrix_plot(b)

    While this returns an error::

        sage: b=random_matrix(CDF,200,sparse=True,density=0.01)
        sage: matrix_plot(b)
        Traceback (most recent call last):
        ...
        ValueError: can not convert entries to floating point numbers

    To plot the absolute value of a complex matrix, use the
    ``apply_map`` method::

        sage: b=random_matrix(CDF,200,sparse=True,density=0.01)
        sage: matrix_plot(b.apply_map(abs))

    Plotting lists of lists also works::

        sage: matrix_plot([[1,3,5,1],[2,4,5,6],[1,3,5,7]])

    As does plotting of NumPy arrays::

        sage: import numpy
        sage: matrix_plot(numpy.random.rand(10, 10))

    TESTS::

        sage: P.<t> = RR[]
        sage: matrix_plot(random_matrix(P, 3, 3))
        Traceback (most recent call last):
        ...
        TypeError: cannot coerce nonconstant polynomial to float

    ::

        sage: matrix_plot([1,2,3])
        Traceback (most recent call last):
        ...
        TypeError: mat must be a Matrix or a two dimensional array

    ::

        sage: matrix_plot([[sin(x), cos(x)], [1, 0]])
        Traceback (most recent call last):
        ...
        ValueError: can not convert entries to floating point numbers

    Test that sparse matrices also work with subdivisions::

        sage: matrix_plot(sparse, subdivisions=True, subdivision_boundaries=[[2,4],[6,8]])
    """
    import numpy as np
    import scipy.sparse as scipysparse
    from sage.plot.plot import Graphics
    from sage.matrix.all import is_Matrix
    from sage.rings.all import RDF
    orig_mat = mat
    if is_Matrix(mat):
        sparse = mat.is_sparse()
        if sparse:
            entries = list(mat._dict().items())
            try:
                data = np.asarray([d for _, d in entries], dtype=float)
            except:
                raise ValueError, "can not convert entries to floating point numbers"
            positions = np.asarray([[row for (row, col), _ in entries],
                                    [col for (row, col), _ in entries]],
                                   dtype=int)
            mat = scipysparse.coo_matrix((data, positions),
                                         shape=(mat.nrows(), mat.ncols()))
        else:
            mat = mat.change_ring(RDF).numpy()
    elif hasattr(mat, 'tocoo'):
        sparse = True
    else:
        sparse = False

    try:
        if sparse:
            xy_data_array = mat
        else:
            xy_data_array = np.asarray(mat, dtype=float)
    except TypeError:
        raise TypeError, "mat must be a Matrix or a two dimensional array"
    except ValueError:
        raise ValueError, "can not convert entries to floating point numbers"

    if len(xy_data_array.shape) < 2:
        raise TypeError, "mat must be a Matrix or a two dimensional array"

    xrange = (0, xy_data_array.shape[1])
    yrange = (0, xy_data_array.shape[0])

    if options['subdivisions'] and options['subdivision_options'][
            'boundaries'] is None:
        options['subdivision_options'][
            'boundaries'] = orig_mat.get_subdivisions()

    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(MatrixPlot(xy_data_array, xrange, yrange, options))
    return g
Esempio n. 43
0
    def plot_two_intervals(
        self, 
        position=(0,0),
        vertical_alignment = 'center',
        horizontal_alignment = 'left',
        interval_height=0.1,
        labels_height=0.05,
        fontsize=14,
        labels=True,
        colors=None):
        r"""
        Returns a picture of the interval exchange transformation.

        INPUT:

        - ``position`` - a 2-uple of the position

        - ``horizontal_alignment`` - left (defaut), center or right

        - ``labels`` - boolean (defaut: True)

        - ``fontsize`` - the size of the label


        OUTPUT:

        2d plot -- a plot of the two intervals (domain and range)

        EXAMPLES::

            sage: t = iet.IntervalExchangeTransformation(('a b','b a'),[1,1])
            sage: t.plot_two_intervals()
        """
        from sage.plot.plot import Graphics
        from sage.plot.plot import line2d
        from sage.plot.plot import text
        from sage.plot.colors import rainbow

        G = Graphics()

        lengths = map(float,self._lengths)
        total_length = sum(lengths)

        if colors is None:
            colors = rainbow(len(self._permutation), 'rgbtuple')

        if horizontal_alignment == 'left':
            s = position[0]
        elif horizontal_alignment == 'center':
            s = position[0] - total_length / 2
        elif horizontal_alignment == 'right':
            s = position[0] - total_length
        else:
            raise ValueError, "horizontal_alignement must be left, center or right"

        top_height = position[1] + interval_height
        for i in self._permutation._intervals[0]:
            G += line2d([(s,top_height),(s+lengths[i],top_height)],
                rgbcolor=colors[i])
            if labels == True:
                G += text(str(self._permutation._alphabet.unrank(i)),
                    (s+float(lengths[i])/2,top_height+labels_height),
                    horizontal_alignment='center',
                    rgbcolor=colors[i],
                    fontsize=fontsize)

            s += lengths[i]

        if horizontal_alignment == 'left':
            s = position[0]
        elif horizontal_alignment == 'center':
            s = position[0] - total_length / 2
        elif horizontal_alignment == 'right':
            s = position[0] - total_length
        else:
            raise ValueError, "horizontal_alignement must be left, center or right"

        bottom_height = position[1] - interval_height
        for i in self._permutation._intervals[1]:
            G += line2d([(s,bottom_height), (s+lengths[i],bottom_height)],
                rgbcolor=colors[i])
            if labels == True:
                G += text(str(self._permutation._alphabet.unrank(i)),
                    (s+float(lengths[i])/2,bottom_height-labels_height),
                    horizontal_alignment='center',
                    rgbcolor=colors[i],
                    fontsize=fontsize)
            s += lengths[i]

        return G
Esempio n. 44
0
def region_plot(f, xrange, yrange, plot_points, incol, outcol, bordercol, borderstyle, borderwidth,**options):
    r"""
    ``region_plot`` takes a boolean function of two variables, `f(x,y)`
    and plots the region where f is True over the specified 
    ``xrange`` and ``yrange`` as demonstrated below.

    ``region_plot(f, (xmin, xmax), (ymin, ymax), ...)``

    INPUT:

    - ``f`` -- a boolean function of two variables

    - ``(xmin, xmax)`` -- 2-tuple, the range of ``x`` values OR 3-tuple
      ``(x,xmin,xmax)``

    - ``(ymin, ymax)`` -- 2-tuple, the range of ``y`` values OR 3-tuple
      ``(y,ymin,ymax)``

    - ``plot_points``  -- integer (default: 100); number of points to plot
      in each direction of the grid

    - ``incol`` -- a color (default: ``'blue'``), the color inside the region

    - ``outcol`` -- a color (default: ``'white'``), the color of the outside
      of the region

    If any of these options are specified, the border will be shown as indicated,
    otherwise it is only implicit (with color ``incol``) as the border of the 
    inside of the region.

     - ``bordercol`` -- a color (default: ``None``), the color of the border
       (``'black'`` if ``borderwidth`` or ``borderstyle`` is specified but not ``bordercol``)

    - ``borderstyle``  -- string (default: 'solid'), one of 'solid', 'dashed', 'dotted', 'dashdot'

    - ``borderwidth``  -- integer (default: None), the width of the border in pixels
 
    - ``legend_label`` -- the label for this item in the legend


    EXAMPLES:

    Here we plot a simple function of two variables::

        sage: x,y = var('x,y')
        sage: region_plot(cos(x^2+y^2) <= 0, (x, -3, 3), (y, -3, 3))
         
    Here we play with the colors::

        sage: region_plot(x^2+y^3 < 2, (x, -2, 2), (y, -2, 2), incol='lightblue', bordercol='gray')
        
    An even more complicated plot, with dashed borders::

        sage: region_plot(sin(x)*sin(y) >= 1/4, (x,-10,10), (y,-10,10), incol='yellow', bordercol='black', borderstyle='dashed', plot_points=250)

    A disk centered at the origin::

        sage: region_plot(x^2+y^2<1, (x,-1,1), (y,-1,1))

    A plot with more than one condition (all conditions must be true for the statement to be true)::

        sage: region_plot([x^2+y^2<1, x<y], (x,-2,2), (y,-2,2))

    Since it doesn't look very good, let's increase ``plot_points``::

        sage: region_plot([x^2+y^2<1, x<y], (x,-2,2), (y,-2,2), plot_points=400)

    To get plots where only one condition needs to be true, use a function.
    Using lambda functions, we definitely need the extra ``plot_points``::

        sage: region_plot(lambda x,y: x^2+y^2<1 or x<y, (x,-2,2), (y,-2,2), plot_points=400)
    
    The first quadrant of the unit circle::

        sage: region_plot([y>0, x>0, x^2+y^2<1], (x,-1.1, 1.1), (y,-1.1, 1.1), plot_points = 400)

    Here is another plot, with a huge border::

        sage: region_plot(x*(x-1)*(x+1)+y^2<0, (x, -3, 2), (y, -3, 3), incol='lightblue', bordercol='gray', borderwidth=10, plot_points=50)

    If we want to keep only the region where x is positive::

        sage: region_plot([x*(x-1)*(x+1)+y^2<0, x>-1], (x, -3, 2), (y, -3, 3), incol='lightblue', plot_points=50)

    Here we have a cut circle::

        sage: region_plot([x^2+y^2<4, x>-1], (x, -2, 2), (y, -2, 2), incol='lightblue', bordercol='gray', plot_points=200)

    The first variable range corresponds to the horizontal axis and
    the second variable range corresponds to the vertical axis::

        sage: s,t=var('s,t')
        sage: region_plot(s>0,(t,-2,2),(s,-2,2))

    ::

        sage: region_plot(s>0,(s,-2,2),(t,-2,2))

    """

    from sage.plot.plot import Graphics
    from sage.plot.misc import setup_for_eval_on_grid
    import numpy

    if not isinstance(f, (list, tuple)):
        f = [f]

    f = [equify(g) for g in f]

    g, ranges = setup_for_eval_on_grid(f, [xrange, yrange], plot_points)
    xrange,yrange=[r[:2] for r in ranges]

    xy_data_arrays = numpy.asarray([[[func(x, y) for x in xsrange(*ranges[0], include_endpoint=True)]
                                     for y in xsrange(*ranges[1], include_endpoint=True)]
                                    for func in g],dtype=float)
    xy_data_array=numpy.abs(xy_data_arrays.prod(axis=0))
    # Now we need to set entries to negative iff all
    # functions were negative at that point.
    neg_indices = (xy_data_arrays<0).all(axis=0)
    xy_data_array[neg_indices]=-xy_data_array[neg_indices]

    from matplotlib.colors import ListedColormap
    incol = rgbcolor(incol)
    outcol = rgbcolor(outcol)
    cmap = ListedColormap([incol, outcol])
    cmap.set_over(outcol)
    cmap.set_under(incol)
    
    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore=['xmin', 'xmax']))
    g.add_primitive(ContourPlot(xy_data_array, xrange,yrange, 
                                dict(contours=[-1e307, 0, 1e307], cmap=cmap, fill=True, **options)))

    if bordercol or borderstyle or borderwidth:
        cmap = [rgbcolor(bordercol)] if bordercol else ['black']
        linestyles = [borderstyle] if borderstyle else None
        linewidths = [borderwidth] if borderwidth else None
        g.add_primitive(ContourPlot(xy_data_array, xrange, yrange, 
                                    dict(linestyles=linestyles, linewidths=linewidths,
                                         contours=[0], cmap=[bordercol], fill=False, **options)))
    
    return g
Esempio n. 45
0
def arc(center, r1, r2=None, angle=0.0, sector=(0.0,2*pi), **options):
    r"""
    An arc (that is a portion of a circle or an ellipse)

    Type ``arc.options`` to see all options.

    INPUT:

    - ``center`` - 2-tuple of real numbers - position of the center.

    - ``r1``, ``r2`` - positive real numbers - radii of the ellipse. If only ``r1`` 
      is set, then the two radii are supposed to be equal and this function returns 
      an arc of of circle.

    - ``angle`` - real number - angle between the horizontal and the axis that
      corresponds to ``r1``.
    
    - ``sector`` - 2-tuple (default: (0,2*pi))- angles sector in which the arc will
      be drawn.

    OPTIONS:

    - ``alpha`` - float (default: 1) - transparency

    - ``thickness`` - float (default: 1) - thickness of the arc

    - ``color``, ``rgbcolor`` - string or 2-tuple (default: 'blue') - the color
      of the arc

    - ``linestyle`` - string (default: 'solid') - the style of the line

    EXAMPLES:

    Plot an arc of circle centered at (0,0) with radius 1 in the sector
    `(\pi/4,3*\pi/4)`::

        sage: arc((0,0), 1, sector=(pi/4,3*pi/4))

    Plot an arc of an ellipse between the angles 0 and `\pi/2`::

        sage: arc((2,3), 2, 1, sector=(0,pi/2))

    Plot an arc of a rotated ellipse between the angles 0 and `\pi/2`::

        sage: arc((2,3), 2, 1, angle=pi/5, sector=(0,pi/2))

    Plot an arc of an ellipse in red with a dashed linestyle::

        sage: arc((0,0), 2, 1, 0, (0,pi/2), linestyle="dashed", color="red")

    The default aspect ratio for arcs is 1.0::

        sage: arc((0,0), 1, sector=(pi/4,3*pi/4)).aspect_ratio()
        1.0

    It is not possible to draw arcs in 3D::

        sage: A = arc((0,0,0), 1)
        Traceback (most recent call last):
        ...
        NotImplementedError
    """
    from sage.plot.plot import Graphics
    if len(center)==2:
        if r2 is None: r2 = r1
        g = Graphics()
        g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
        if len(sector) != 2:
            raise ValueError, "the sector must consist of two angles"
        g.add_primitive(Arc(
            center[0],center[1],
            r1,r2,
            angle,
            sector[0],sector[1],
            options))
        return g
    elif len(center)==3:
        raise NotImplementedError