Example #1
0
def _parametric_plot3d_curve(f, urange, plot_points, **kwds):
    r"""
    This function is used internally by the
    ``parametric_plot3d`` command.
    """
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid(f, [urange], plot_points)
    f_x,f_y,f_z = g
    w = [(f_x(u), f_y(u), f_z(u)) for u in xsrange(*ranges[0], include_endpoint=True)]
    return line3d(w, **kwds)
Example #2
0
def _parametric_plot3d_curve(f, urange, plot_points, **kwds):
    r"""
    This function is used internally by the
    ``parametric_plot3d`` command.
    """
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid(f, [urange], plot_points)
    f_x, f_y, f_z = g
    w = [(f_x(u), f_y(u), f_z(u))
         for u in xsrange(*ranges[0], include_endpoint=True)]
    return line3d(w, **kwds)
Example #3
0
def _parametric_plot3d_curve(f, urange, plot_points, **kwds):
    r"""
    Return a parametric three-dimensional space curve.
    This function is used internally by the
    :func:`parametric_plot3d` command.

    There are two ways this function is invoked by
    :func:`parametric_plot3d`.

    - ``parametric_plot3d([f_x, f_y, f_z], (u_min,
      u_max))``:
      `f_x, f_y, f_z` are three functions and
      `u_{\min}` and `u_{\max}` are real numbers

    - ``parametric_plot3d([f_x, f_y, f_z], (u, u_min,
      u_max))``:
      `f_x, f_y, f_z` can be viewed as functions of
      `u`

    INPUT:

    - ``f`` - a 3-tuple of functions or expressions, or vector of size 3

    - ``urange`` - a 2-tuple (u_min, u_max) or a 3-tuple
      (u, u_min, u_max)

    - ``plot_points`` - (default: "automatic", which is 75) initial
      number of sample points in each parameter; an integer.

    EXAMPLES:

    We demonstrate each of the two ways of calling this.  See
    :func:`parametric_plot3d` for many more examples.

    We do the first one with a lambda function, which creates a
    callable Python function that sends `u` to `u/10`::

        sage: parametric_plot3d((sin, cos, lambda u: u/10), (0,20)) # indirect doctest
        Graphics3d Object

    Now we do the same thing with symbolic expressions::

        sage: u = var('u')
        sage: parametric_plot3d((sin(u), cos(u), u/10), (u,0,20))
        Graphics3d Object

    """
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid(f, [urange], plot_points)
    f_x, f_y, f_z = g
    w = [(f_x(u), f_y(u), f_z(u))
         for u in xsrange(*ranges[0], include_endpoint=True)]
    return line3d(w, **kwds)
Example #4
0
def _parametric_plot3d_curve(f, urange, plot_points, **kwds):
    r"""
    Return a parametric three-dimensional space curve.
    This function is used internally by the
    :func:`parametric_plot3d` command.

    There are two ways this function is invoked by
    :func:`parametric_plot3d`.

    - ``parametric_plot3d([f_x, f_y, f_z], (u_min,
      u_max))``:
      `f_x, f_y, f_z` are three functions and
      `u_{\min}` and `u_{\max}` are real numbers

    - ``parametric_plot3d([f_x, f_y, f_z], (u, u_min,
      u_max))``:
      `f_x, f_y, f_z` can be viewed as functions of
      `u`

    INPUT:

    - ``f`` - a 3-tuple of functions or expressions, or vector of size 3

    - ``urange`` - a 2-tuple (u_min, u_max) or a 3-tuple
      (u, u_min, u_max)

    - ``plot_points`` - (default: "automatic", which is 75) initial
      number of sample points in each parameter; an integer.

    EXAMPLES:

    We demonstrate each of the two ways of calling this.  See
    :func:`parametric_plot3d` for many more examples.

    We do the first one with a lambda function, which creates a
    callable Python function that sends `u` to `u/10`::

        sage: parametric_plot3d((sin, cos, lambda u: u/10), (0,20)) # indirect doctest
        Graphics3d Object

    Now we do the same thing with symbolic expressions::

        sage: u = var('u')
        sage: parametric_plot3d((sin(u), cos(u), u/10), (u,0,20))
        Graphics3d Object

    """
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid(f, [urange], plot_points)
    f_x, f_y, f_z = g
    w = [(f_x(u), f_y(u), f_z(u)) for u in xsrange(*ranges[0], include_endpoint=True)]
    return line3d(w, **kwds)
Example #5
0
def _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style, **kwds):
    r"""
    This function is used internally by the
    ``parametric_plot3d`` command.
    """
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid(f, [urange,vrange], plot_points)
    urange = srange(*ranges[0], include_endpoint=True)
    vrange = srange(*ranges[1], include_endpoint=True)
    G = ParametricSurface(g, (urange, vrange), **kwds)
    
    if boundary_style is not None:
        for u in (urange[0], urange[-1]):
            G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for v in vrange], **boundary_style)
        for v in (vrange[0], vrange[-1]):
            G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for u in urange], **boundary_style)
    return G
Example #6
0
def _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style,
                               **kwds):
    r"""
    This function is used internally by the
    ``parametric_plot3d`` command.
    """
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid(f, [urange, vrange], plot_points)
    urange = srange(*ranges[0], include_endpoint=True)
    vrange = srange(*ranges[1], include_endpoint=True)
    G = ParametricSurface(g, (urange, vrange), **kwds)

    if boundary_style is not None:
        for u in (urange[0], urange[-1]):
            G += line3d([(g[0](u, v), g[1](u, v), g[2](u, v)) for v in vrange],
                        **boundary_style)
        for v in (vrange[0], vrange[-1]):
            G += line3d([(g[0](u, v), g[1](u, v), g[2](u, v)) for u in urange],
                        **boundary_style)
    return G
Example #7
0
        sage: x,y = var('x,y')
        sage: plot_vector_field( (-x/sqrt(x^2+y^2), -y/sqrt(x^2+y^2)), (x, -10, 10), (y, -10, 10))

    ::

        sage: x,y = var('x,y')
        sage: plot_vector_field( (-x/sqrt(x+y), -y/sqrt(x+y)), (x, -10, 10), (y, -10, 10))

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

        sage: plot_vector_field((x, y), (x, -2, 2), (y, -2, 2), xmax=10)
        sage: plot_vector_field((x, y), (x, -2, 2), (y, -2, 2)).show(xmax=10) # These are equivalent
    """
    from sage.plot.plot import Graphics
    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))
Example #8
0
        sage: x,y = var('x,y')
        sage: plot_vector_field( (-x/sqrt(x^2+y^2), -y/sqrt(x^2+y^2)), (x, -10, 10), (y, -10, 10))

    ::

        sage: x,y = var('x,y')
        sage: plot_vector_field( (-x/sqrt(x+y), -y/sqrt(x+y)), (x, -10, 10), (y, -10, 10))

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

        sage: plot_vector_field((x, y), (x, -2, 2), (y, -2, 2), xmax=10)
        sage: plot_vector_field((x, y), (x, -2, 2), (y, -2, 2)).show(xmax=10) # These are equivalent
    """
    from sage.plot.plot import Graphics
    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))
Example #9
0
def plot_vector_field3d(functions, xrange, yrange, zrange, plot_points=5, colors="jet", center_arrows=False, **kwds):
    r"""
    Plot a 3d vector field

    INPUT:

    - ``functions`` - a list of three functions, representing the x-,
      y-, and z-coordinates of a vector

    - ``xrange``, ``yrange``, and ``zrange`` - three tuples of the
      form (var, start, stop), giving the variables and ranges for each axis

    - ``plot_points`` (default 5) - either a number or list of three
      numbers, specifying how many points to plot for each axis

    - ``colors`` (default 'jet') - a color, list of colors (which are
      interpolated between), or matplotlib colormap name, giving the coloring
      of the arrows.  If a list of colors or a colormap is given,
      coloring is done as a function of length of the vector

    - ``center_arrows`` (default False) - If True, draw the arrows
      centered on the points; otherwise, draw the arrows with the tail
      at the point

    - any other keywords are passed on to the plot command for each arrow

    EXAMPLES::

        sage: x,y,z=var('x y z')
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi))
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),colors=['red','green','blue'])
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),colors='red')
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),plot_points=4)
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),plot_points=[3,5,7])
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),center_arrows=True)

    TESTS:

    This tests that :trac:`2100` is fixed in a way compatible with this command::

        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),center_arrows=True,aspect_ratio=(1,2,1))
    """
    (ff, gg, hh), ranges = setup_for_eval_on_grid(functions, [xrange, yrange, zrange], plot_points)
    xpoints, ypoints, zpoints = [srange(*r, include_endpoint=True) for r in ranges]
    points = [vector((i, j, k)) for i in xpoints for j in ypoints for k in zpoints]
    vectors = [vector((ff(*point), gg(*point), hh(*point))) for point in points]

    try:
        from matplotlib.cm import get_cmap

        cm = get_cmap(colors)
    except (TypeError, ValueError):
        cm = None
    if cm is None:
        if isinstance(colors, (list, tuple)):
            from matplotlib.colors import LinearSegmentedColormap

            cm = LinearSegmentedColormap.from_list("mymap", colors)
        else:
            cm = lambda x: colors

    max_len = max(v.norm() for v in vectors)
    scaled_vectors = [v / max_len for v in vectors]

    if center_arrows:
        return sum([plot(v, color=cm(v.norm()), **kwds).translate(p - v / 2) for v, p in zip(scaled_vectors, points)])
    else:
        return sum([plot(v, color=cm(v.norm()), **kwds).translate(p) for v, p in zip(scaled_vectors, points)])
Example #10
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'``, respectively ``'-'``,
      ``'--'``, ``':'``, ``'-.'``.

    - ``borderwidth``  -- integer (default: None), the width of the border in pixels

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

    - ``base`` - (default: 10) the base of the logarithm if
      a logarithmic scale is set. This must be greater than 1. The base
      can be also given as a list or tuple ``(basex, basey)``.
      ``basex`` sets the base of the logarithm along the horizontal
      axis and ``basey`` sets the base along the vertical axis.

    - ``scale`` -- (default: ``"linear"``) string. The scale of the axes.
      Possible values are ``"linear"``, ``"loglog"``, ``"semilogx"``,
      ``"semilogy"``.

      The scale can be also be given as single argument that is a list
      or tuple ``(scale, base)`` or ``(scale, basex, basey)``.

      The ``"loglog"`` scale sets both the horizontal and vertical axes to
      logarithmic scale. The ``"semilogx"`` scale sets the horizontal axis
      to logarithmic scale. The ``"semilogy"`` scale sets the vertical axis
      to logarithmic scale. The ``"linear"`` scale is the default value
      when :class:`~sage.plot.graphics.Graphics` is initialized.


    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))
        Graphics object consisting of 1 graphics primitive

    Here we play with the colors::

        sage: region_plot(x^2+y^3 < 2, (x, -2, 2), (y, -2, 2), incol='lightblue', bordercol='gray')
        Graphics object consisting of 2 graphics primitives

    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)
        Graphics object consisting of 2 graphics primitives

    A disk centered at the origin::

        sage: region_plot(x^2+y^2<1, (x,-1,1), (y,-1,1))
        Graphics object consisting of 1 graphics primitive

    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))
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 2 graphics primitives

    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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 2 graphics primitives

    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))
        Graphics object consisting of 1 graphics primitive

    ::

        sage: region_plot(s>0,(s,-2,2),(t,-2,2))
        Graphics object consisting of 1 graphics primitive

    An example of a region plot in 'loglog' scale::

        sage: region_plot(x^2+y^2<100, (x,1,10), (y,1,10), scale='loglog')
        Graphics object consisting of 1 graphics primitive

    """

    from sage.plot.all 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()

    # Reset aspect_ratio to 'automatic' in case scale is 'semilog[xy]'.
    # Otherwise matplotlib complains.
    scale = options.get('scale', None)
    if isinstance(scale, (list, tuple)):
        scale = scale[0]
    if scale == 'semilogy' or scale == 'semilogx':
        options['aspect_ratio'] = 'automatic'

    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
Example #11
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))
        Graphics object consisting of 1 graphics primitive


    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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    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))
        Graphics object consisting of 1 graphics primitive

    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))
        Graphics object consisting of 1 graphics primitive

    ::

        sage: density_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi))
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    ::

        sage: density_plot(log(x) + log(y), (x, 1, 10), (y, 1, 10)).show(dpi=20) # These are equivalent

    TESTS:

    Check that :trac:`15315` is fixed, i.e., density_plot respects the
    ``aspect_ratio`` parameter. Without the fix, it looks like a thin line
    of width a few mm. With the fix it should look like a nice fat layered
    image::

        sage: density_plot((x*y)^(1/2), (x,0,3), (y,0,500), aspect_ratio=.01)
        Graphics object consisting of 1 graphics primitive

    Default ``aspect_ratio`` is ``"automatic"``, and that should work too::

        sage: density_plot((x*y)^(1/2), (x,0,3), (y,0,500))
        Graphics object consisting of 1 graphics primitive

    """
    from sage.plot.all 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
Example #12
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
Example #13
0
def plot_vector_field3d(functions, xrange, yrange, zrange,
                        plot_points=5, colors='jet', center_arrows=False, **kwds):
    r"""
    Plot a 3d vector field

    INPUT:

    - ``functions`` - a list of three functions, representing the x-,
      y-, and z-coordinates of a vector

    - ``xrange``, ``yrange``, and ``zrange`` - three tuples of the
      form (var, start, stop), giving the variables and ranges for each axis

    - ``plot_points`` (default 5) - either a number or list of three
      numbers, specifying how many points to plot for each axis

    - ``colors`` (default 'jet') - a color, list of colors (which are
      interpolated between), or matplotlib colormap name, giving the coloring
      of the arrows.  If a list of colors or a colormap is given,
      coloring is done as a function of length of the vector

    - ``center_arrows`` (default False) - If True, draw the arrows
      centered on the points; otherwise, draw the arrows with the tail
      at the point

    - any other keywords are passed on to the plot command for each arrow

    EXAMPLES::

        sage: x,y,z=var('x y z')
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi))
        Graphics3d Object
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),colors=['red','green','blue'])
        Graphics3d Object
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),colors='red')
        Graphics3d Object
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),plot_points=4)
        Graphics3d Object
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),plot_points=[3,5,7])
        Graphics3d Object
        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),center_arrows=True)
        Graphics3d Object

    TESTS:

    This tests that :trac:`2100` is fixed in a way compatible with this command::

        sage: plot_vector_field3d((x*cos(z),-y*cos(z),sin(z)), (x,0,pi), (y,0,pi), (z,0,pi),center_arrows=True,aspect_ratio=(1,2,1))
        Graphics3d Object
    """
    (ff,gg,hh), ranges = setup_for_eval_on_grid(functions, [xrange, yrange, zrange], plot_points)
    xpoints, ypoints, zpoints = [srange(*r, include_endpoint=True) for r in ranges]
    points = [vector((i,j,k)) for i in xpoints for j in ypoints for k in zpoints]
    vectors = [vector((ff(*point), gg(*point), hh(*point))) for point in points]

    try:
        from matplotlib.cm import get_cmap
        cm = get_cmap(colors)
    except (TypeError, ValueError):
        cm = None
    if cm is None:
        if isinstance(colors, (list, tuple)):
            from matplotlib.colors import LinearSegmentedColormap
            cm = LinearSegmentedColormap.from_list('mymap',colors)
        else:
            cm = lambda x: colors

    max_len = max(v.norm() for v in vectors)
    scaled_vectors = [v/max_len for v in vectors]

    if center_arrows:
        G = sum([plot(v,color=cm(v.norm()),**kwds).translate(p-v/2) for v,p in zip(scaled_vectors, points)])
        G._set_extra_kwds(kwds)
        return G
    else:
        G = sum([plot(v,color=cm(v.norm()),**kwds).translate(p) for v,p in zip(scaled_vectors, points)])
        G._set_extra_kwds(kwds)
        return G
Example #14
0
def _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style,
                               **kwds):
    r"""
    Return a parametric three-dimensional space surface.
    This function is used internally by the
    :func:`parametric_plot3d` command.

    There are two ways this function is invoked by
    :func:`parametric_plot3d`.

    - ``parametric_plot3d([f_x, f_y, f_z], (u_min, u_max),
      (v_min, v_max))``:
      `f_x, f_y, f_z` are each functions of two variables

    - ``parametric_plot3d([f_x, f_y, f_z], (u, u_min,
      u_max), (v, v_min, v_max))``:
      `f_x, f_y, f_z` can be viewed as functions of
      `u` and `v`

    INPUT:

    - ``f`` - a 3-tuple of functions or expressions, or vector of size 3

    - ``urange`` - a 2-tuple (u_min, u_max) or a 3-tuple
      (u, u_min, u_max)

    - ``vrange`` - a 2-tuple (v_min, v_max) or a 3-tuple
      (v, v_min, v_max)

    - ``plot_points`` - (default: "automatic", which is [40,40]
      for surfaces) initial number of sample points in each parameter;
      a pair of integers.

    - ``boundary_style`` - (default: None, no boundary) a dict that describes
      how to draw the boundaries of regions by giving options that are passed
      to the line3d command.

    EXAMPLES:

    We demonstrate each of the two ways of calling this.  See
    :func:`parametric_plot3d` for many more examples.

    We do the first one with lambda functions::

        sage: f = (lambda u,v: cos(u), lambda u,v: sin(u)+cos(v), lambda u,v: sin(v))
        sage: parametric_plot3d(f, (0, 2*pi), (-pi, pi)) # indirect doctest
        Graphics3d Object

    Now we do the same thing with symbolic expressions::

        sage: u, v = var('u,v')
        sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), mesh=True)
        Graphics3d Object
    """
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid(f, [urange, vrange], plot_points)
    urange = srange(*ranges[0], include_endpoint=True)
    vrange = srange(*ranges[1], include_endpoint=True)
    G = ParametricSurface(g, (urange, vrange), **kwds)

    if boundary_style is not None:
        for u in (urange[0], urange[-1]):
            G += line3d([(g[0](u, v), g[1](u, v), g[2](u, v)) for v in vrange],
                        **boundary_style)
        for v in (vrange[0], vrange[-1]):
            G += line3d([(g[0](u, v), g[1](u, v), g[2](u, v)) for u in urange],
                        **boundary_style)
    return G
from sage.misc.decorators import options
@options(plot_points=20)
def plot_vector_field_on_curve( (xf, yf), (x, y), range, **options ):
    r"""Plot values of a vector-values function along points of a curve
    in the plane.

    Note this function doesn't plot the curve itself."""
    from sage.plot.all import Graphics
    from sage.misc.misc import xsrange
    from sage.plot.plot_field import PlotField
    from sage.plot.misc import setup_for_eval_on_grid
    zz, rangez = setup_for_eval_on_grid( (x, y, xf, yf), [ range ], options['plot_points'] )
    #print 'setup: ', zz, rangez
    x, y, xf, yf = zz
    xpos_array, ypos_array, xvec_array, yvec_array = [],[],[],[]
    for t in xsrange( *rangez[0], include_endpoint=True ):
       xpos_array.append( x(t) )
       ypos_array.append( y(t) )
       xvec_array.append( xf(t) )
       yvec_array.append( yf(t) )
    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

Example #16
0
def region_plot(f, xrange, yrange, plot_points, incol, outcol, bordercol, borderstyle, borderwidth, alpha, **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 or a list of boolean functions 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: ``None``), 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'``, respectively ``'-'``,
      ``'--'``, ``':'``, ``'-.'``.

    - ``borderwidth``  -- integer (default: None), the width of the border in pixels

    - ``alpha`` -- (default: 1) How transparent the fill is. A number between 0 and 1.

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

    - ``base`` - (default: 10) the base of the logarithm if
      a logarithmic scale is set. This must be greater than 1. The base
      can be also given as a list or tuple ``(basex, basey)``.
      ``basex`` sets the base of the logarithm along the horizontal
      axis and ``basey`` sets the base along the vertical axis.

    - ``scale`` -- (default: ``"linear"``) string. The scale of the axes.
      Possible values are ``"linear"``, ``"loglog"``, ``"semilogx"``,
      ``"semilogy"``.

      The scale can be also be given as single argument that is a list
      or tuple ``(scale, base)`` or ``(scale, basex, basey)``.

      The ``"loglog"`` scale sets both the horizontal and vertical axes to
      logarithmic scale. The ``"semilogx"`` scale sets the horizontal axis
      to logarithmic scale. The ``"semilogy"`` scale sets the vertical axis
      to logarithmic scale. The ``"linear"`` scale is the default value
      when :class:`~sage.plot.graphics.Graphics` is initialized.


    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))
        Graphics object consisting of 1 graphics primitive

    Here we play with the colors::

        sage: region_plot(x^2+y^3 < 2, (x, -2, 2), (y, -2, 2), incol='lightblue', bordercol='gray')
        Graphics object consisting of 2 graphics primitives

    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)
        Graphics object consisting of 2 graphics primitives

    A disk centered at the origin::

        sage: region_plot(x^2+y^2<1, (x,-1,1), (y,-1,1))
        Graphics object consisting of 1 graphics primitive

    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))
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 2 graphics primitives

    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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 2 graphics primitives

    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))
        Graphics object consisting of 1 graphics primitive

    ::

        sage: region_plot(s>0,(s,-2,2),(t,-2,2))
        Graphics object consisting of 1 graphics primitive

    An example of a region plot in 'loglog' scale::

        sage: region_plot(x^2+y^2<100, (x,1,10), (y,1,10), scale='loglog')
        Graphics object consisting of 1 graphics primitive

    TESTS:

    To check that :trac:`16907` is fixed::

        sage: x, y = var('x, y')
        sage: disc1 = region_plot(x^2+y^2 < 1, (x, -1, 1), (y, -1, 1), alpha=0.5)
        sage: disc2 = region_plot((x-0.7)^2+(y-0.7)^2 < 0.5, (x, -2, 2), (y, -2, 2), incol='red', alpha=0.5)
        sage: disc1 + disc2
        Graphics object consisting of 2 graphics primitives

    To check that :trac:`18286` is fixed::
        sage: x, y = var('x, y')
        sage: region_plot([x == 0], (x, -1, 1), (y, -1, 1))
        Graphics object consisting of 1 graphics primitive
        sage: region_plot([x^2+y^2==1, x<y], (x, -1, 1), (y, -1, 1))
        Graphics object consisting of 1 graphics primitive

    """

    from sage.plot.all import Graphics
    from sage.plot.misc import setup_for_eval_on_grid
    from sage.symbolic.expression import is_Expression
    from warnings import warn
    import numpy

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

    feqs = [equify(g) for g in f if is_Expression(g) and g.operator() is operator.eq and not equify(g).is_zero()]
    f = [equify(g) for g in f if not (is_Expression(g) and g.operator() is operator.eq)]
    neqs = len(feqs)
    if neqs > 1:
        warn("There are at least 2 equations; If the region is degenerated to points, plotting might show nothing.")
        feqs = [sum([fn**2 for fn in feqs])]
        neqs = 1
    if neqs and not bordercol:
        bordercol = incol
    if not f:
        return implicit_plot(feqs[0], xrange, yrange, plot_points=plot_points, fill=False, \
                             linewidth=borderwidth, linestyle=borderstyle, color=bordercol, **options)
    f_all, ranges = setup_for_eval_on_grid(feqs + 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 f_all[neqs::]],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)
    if outcol:
        outcol = rgbcolor(outcol)
        cmap = ListedColormap([incol, outcol])
        cmap.set_over(outcol, alpha=alpha)
    else:
        outcol = rgbcolor('white')
        cmap = ListedColormap([incol, outcol])
        cmap.set_over(outcol, alpha=0)
    cmap.set_under(incol, alpha=alpha)

    g = Graphics()

    # Reset aspect_ratio to 'automatic' in case scale is 'semilog[xy]'.
    # Otherwise matplotlib complains.
    scale = options.get('scale', None)
    if isinstance(scale, (list, tuple)):
        scale = scale[0]
    if scale == 'semilogy' or scale == 'semilogx':
        options['aspect_ratio'] = 'automatic'

    g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore=['xmin', 'xmax']))

    if neqs == 0:
        g.add_primitive(ContourPlot(xy_data_array, xrange,yrange,
                                dict(contours=[-1e-20, 0, 1e-20], cmap=cmap, fill=True, **options)))
    else:
        mask = numpy.asarray([[elt > 0 for elt in rows] for rows in xy_data_array], dtype=bool)
        xy_data_array = numpy.asarray([[f_all[0](x, y) for x in xsrange(*ranges[0], include_endpoint=True)]
                                        for y in xsrange(*ranges[1], include_endpoint=True)], dtype=float)
        xy_data_array[mask] = None
    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
Example #17
0
def streamline_plot(f_g, xrange, yrange, **options):
    r"""
    Return a streamline plot in a vector field.

    ``streamline_plot`` can take either one or two functions. Consider
    two variables `x` and `y`.

    If given two functions `(f(x,y), g(x,y))`, then this function plots
    streamlines in the vector field over the specified ranges with ``xrange``
    being of `x`, denoted by ``xvar`` below, between ``xmin`` and ``xmax``,
    and ``yrange`` similarly (see below). ::

        streamline_plot((f, g), (xvar, xmin, xmax), (yvar, ymin, ymax))

    Similarly, if given one function `f(x, y)`, then this function plots
    streamlines in the slope field `dy/dx = f(x,y)` over the specified
    ranges as given above.

    PLOT OPTIONS:

    - ``plot_points`` -- (default: 200) the minimal number of plot points

    - ``density`` -- float (default: 1.); controls the closeness of
      streamlines

    - ``start_points`` -- (optional) list of coordinates of starting
      points for the streamlines; coordinate pairs can be tuples or lists

    EXAMPLES:

    Plot some vector fields involving `\sin` and `\cos`::

        sage: x, y = var('x y')
        sage: streamline_plot((sin(x), cos(y)), (x,-3,3), (y,-3,3))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((sin(x), cos(y)), (x,-3,3), (y,-3,3))
        sphinx_plot(g)

    ::

        sage: streamline_plot((y, (cos(x)-2) * sin(x)), (x,-pi,pi), (y,-pi,pi))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((y, (cos(x)-2) * sin(x)), (x,-pi,pi), (y,-pi,pi))
        sphinx_plot(g)

    We increase the density of the plot::

        sage: streamline_plot((y, (cos(x)-2) * sin(x)), (x,-pi,pi), (y,-pi,pi), density=2)
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((y, (cos(x)-2) * sin(x)), (x,-pi,pi), (y,-pi,pi), density=2)
        sphinx_plot(g)

    We ignore function values that are infinite or NaN::

        sage: x, y = var('x y')
        sage: streamline_plot((-x/sqrt(x^2+y^2), -y/sqrt(x^2+y^2)), (x,-10,10), (y,-10,10))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((-x/sqrt(x**2+y**2), -y/sqrt(x**2+y**2)), (x,-10,10), (y,-10,10))
        sphinx_plot(g)

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

        sage: streamline_plot((x, y), (x,-2,2), (y,-2,2), xmax=10)
        Graphics object consisting of 1 graphics primitive
        sage: streamline_plot((x, y), (x,-2,2), (y,-2,2)).show(xmax=10) # These are equivalent

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((x, y), (x,-2,2), (y,-2,2), xmax=10)
        sphinx_plot(g)

    We can also construct streamlines in a slope field::

        sage: x, y = var('x y')
        sage: streamline_plot((x + y) / sqrt(x^2 + y^2), (x,-3,3), (y,-3,3))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((x + y) / sqrt(x**2 + y**2), (x,-3,3), (y,-3,3))
        sphinx_plot(g)

    We choose some particular points the streamlines pass through::

        sage: pts = [[1, 1], [-2, 2], [1, -3/2]]
        sage: g = streamline_plot((x + y) / sqrt(x^2 + y^2), (x,-3,3), (y,-3,3), start_points=pts)
        sage: g += point(pts, color='red')
        sage: g
        Graphics object consisting of 2 graphics primitives

    .. PLOT::

        x, y = var('x y')
        pts = [[1, 1], [-2, 2], [1, -3/2]]
        g = streamline_plot((x + y) / sqrt(x**2 + y**2), (x,-3,3), (y,-3,3), start_points=pts)
        g += point(pts, color='red')
        sphinx_plot(g)

    .. NOTE::

        Streamlines currently pass close to ``start_points`` but do
        not necessarily pass directly through them. That is part of
        the behavior of matplotlib, not an error on your part.

    """
    # Parse the function input
    if isinstance(f_g, (list, tuple)):
        (f, g) = f_g
    else:
        from sage.functions.all import sqrt
        from inspect import isfunction
        if isfunction(f_g):
            f = lambda x, y: 1 / sqrt(f_g(x, y)**2 + 1)
            g = lambda x, y: f_g(x, y) * f(x, y)
        else:
            f = 1 / sqrt(f_g**2 + 1)
            g = f_g * f

    from sage.plot.all import Graphics
    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

    # The density values must be floats
    if isinstance(options['density'], (list, tuple)):
        options['density'] = [float(x) for x in options['density']]
    else:
        options['density'] = float(options['density'])

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

    import numpy
    xpos_array = numpy.array(xpos_array, dtype=float)
    ypos_array = numpy.array(ypos_array, dtype=float)
    xvec_array = numpy.ma.masked_invalid(numpy.array(xvec_array, dtype=float))
    yvec_array = numpy.ma.masked_invalid(numpy.array(yvec_array, dtype=float))

    if 'start_points' in options:
        xstart_array, ystart_array = [], []
        for point in options['start_points']:
            xstart_array.append(point[0])
            ystart_array.append(point[1])
        options['start_points'] = numpy.array([xstart_array, ystart_array]).T

    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(
        StreamlinePlot(xpos_array, ypos_array, xvec_array, yvec_array,
                       options))
    return g
Example #18
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
Example #19
0
def plot_vector_field(f_g, xrange, yrange, **options):
    r"""
    ``plot_vector_field`` takes two functions of two variables xvar and yvar
    (for instance, if the variables are `x` and `y`, take `(f(x,y), g(x,y))`)
    and plots vector arrows of the function over the specified ranges, with
    xrange being of xvar between xmin and xmax, and yrange similarly (see below).

    ``plot_vector_field((f, g), (xvar, xmin, xmax), (yvar, ymin, ymax))``

    EXAMPLES:

    Plot some vector fields involving sin and cos::

        sage: x,y = var('x y')
        sage: plot_vector_field((sin(x), cos(y)), (x,-3,3), (y,-3,3))
        Graphics object consisting of 1 graphics primitive

    ::

        sage: plot_vector_field(( y, (cos(x)-2)*sin(x)), (x,-pi,pi), (y,-pi,pi))
        Graphics object consisting of 1 graphics primitive

    Plot a gradient field::

        sage: u,v = var('u v')
        sage: f = exp(-(u^2+v^2))
        sage: plot_vector_field(f.gradient(), (u,-2,2), (v,-2,2), color='blue')
        Graphics object consisting of 1 graphics primitive

    Plot two orthogonal vector fields::

        sage: x,y = var('x,y')
        sage: a=plot_vector_field((x,y), (x,-3,3),(y,-3,3),color='blue')
        sage: b=plot_vector_field((y,-x),(x,-3,3),(y,-3,3),color='red')
        sage: show(a+b)

    We ignore function values that are infinite or NaN::

        sage: x,y = var('x,y')
        sage: plot_vector_field( (-x/sqrt(x^2+y^2), -y/sqrt(x^2+y^2)), (x, -10, 10), (y, -10, 10))
        Graphics object consisting of 1 graphics primitive

    ::

        sage: x,y = var('x,y')
        sage: plot_vector_field( (-x/sqrt(x+y), -y/sqrt(x+y)), (x, -10, 10), (y, -10, 10))
        Graphics object consisting of 1 graphics primitive

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

        sage: plot_vector_field((x, y), (x, -2, 2), (y, -2, 2), xmax=10)
        Graphics object consisting of 1 graphics primitive
        sage: plot_vector_field((x, y), (x, -2, 2), (y, -2, 2)).show(xmax=10) # These are equivalent
    """
    (f, g) = f_g
    from sage.plot.all import Graphics
    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
Example #20
0
def plot_vector_field(f_g, xrange, yrange, **options):
    r"""
    ``plot_vector_field`` takes two functions of two variables xvar and yvar
    (for instance, if the variables are `x` and `y`, take `(f(x,y), g(x,y))`)
    and plots vector arrows of the function over the specified ranges, with
    xrange being of xvar between xmin and xmax, and yrange similarly (see below).

    ``plot_vector_field((f, g), (xvar, xmin, xmax), (yvar, ymin, ymax))``

    EXAMPLES:

    Plot some vector fields involving sin and cos::

        sage: x,y = var('x y')
        sage: plot_vector_field((sin(x), cos(y)), (x,-3,3), (y,-3,3))
        Graphics object consisting of 1 graphics primitive

    ::

        sage: plot_vector_field(( y, (cos(x)-2)*sin(x)), (x,-pi,pi), (y,-pi,pi))
        Graphics object consisting of 1 graphics primitive

    Plot a gradient field::

        sage: u,v = var('u v')
        sage: f = exp(-(u^2+v^2))
        sage: plot_vector_field(f.gradient(), (u,-2,2), (v,-2,2), color='blue')
        Graphics object consisting of 1 graphics primitive

    Plot two orthogonal vector fields::

        sage: x,y = var('x,y')
        sage: a=plot_vector_field((x,y), (x,-3,3),(y,-3,3),color='blue')
        sage: b=plot_vector_field((y,-x),(x,-3,3),(y,-3,3),color='red')
        sage: show(a+b)

    We ignore function values that are infinite or NaN::

        sage: x,y = var('x,y')
        sage: plot_vector_field( (-x/sqrt(x^2+y^2), -y/sqrt(x^2+y^2)), (x, -10, 10), (y, -10, 10))
        Graphics object consisting of 1 graphics primitive

    ::

        sage: x,y = var('x,y')
        sage: plot_vector_field( (-x/sqrt(x+y), -y/sqrt(x+y)), (x, -10, 10), (y, -10, 10))
        Graphics object consisting of 1 graphics primitive

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

        sage: plot_vector_field((x, y), (x, -2, 2), (y, -2, 2), xmax=10)
        Graphics object consisting of 1 graphics primitive
        sage: plot_vector_field((x, y), (x, -2, 2), (y, -2, 2)).show(xmax=10) # These are equivalent
    """
    (f, g) = f_g
    from sage.plot.all import Graphics
    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
Example #21
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        
Example #22
0
def plot3d_adaptive(f, x_range, y_range, color="automatic",
                    grad_f=None,
                    max_bend=.5, max_depth=5, initial_depth=4, num_colors=128, **kwds):
    r"""
    Adaptive 3d plotting of a function of two variables.

    This is used internally by the plot3d command when the option
    ``adaptive=True`` is given.

    INPUT:


    -  ``f`` - a symbolic function or a Python function of
       3 variables.

    -  ``x_range`` - x range of values: 2-tuple (xmin,
       xmax) or 3-tuple (x,xmin,xmax)

    -  ``y_range`` - y range of values: 2-tuple (ymin,
       ymax) or 3-tuple (y,ymin,ymax)

    -  ``grad_f`` - gradient of f as a Python function

    -  ``color`` - "automatic" - a rainbow of num_colors
       colors

    -  ``num_colors`` - (default: 128) number of colors to
       use with default color

    -  ``max_bend`` - (default: 0.5)

    -  ``max_depth`` - (default: 5)

    -  ``initial_depth`` - (default: 4)

    -  ``**kwds`` - standard graphics parameters


    EXAMPLES:

    We plot `\sin(xy)`::

        sage: from sage.plot.plot3d.plot3d import plot3d_adaptive
        sage: x,y=var('x,y'); plot3d_adaptive(sin(x*y), (x,-pi,pi), (y,-pi,pi), initial_depth=5)
        Graphics3d Object
        
    .. PLOT::
        
        from sage.plot.plot3d.plot3d import plot3d_adaptive
        x,y=var('x,y')
        sphinx_plot(plot3d_adaptive(sin(x*y), (x,-pi,pi), (y,-pi,pi), initial_depth=5))

    """
    if initial_depth >= max_depth:
        max_depth = initial_depth

    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid(f, [x_range,y_range], plot_points=2)
    xmin,xmax = ranges[0][:2]
    ymin,ymax = ranges[1][:2]

    opacity = kwds.get('opacity',1)

    if color == "automatic":
        texture = rainbow(num_colors, 'rgbtuple')
    else:
        if isinstance(color, list):
            texture = color
        else:
            kwds['color'] = color
            texture = Texture(kwds)

    factory = TrivialTriangleFactory()
    plot = TrianglePlot(factory, g, (xmin, xmax), (ymin, ymax), g = grad_f,
                        min_depth=initial_depth, max_depth=max_depth,
                        max_bend=max_bend, num_colors = None)

    P = IndexFaceSet(plot._objects)
    if isinstance(texture, (list, tuple)):
        if len(texture) == 2:
            # do a grid coloring
            xticks = (xmax - xmin)/2**initial_depth
            yticks = (ymax - ymin)/2**initial_depth
            parts = P.partition(lambda x,y,z: (int((x-xmin)/xticks) + int((y-ymin)/yticks)) % 2)
        else:
            # do a topo coloring
            bounds = P.bounding_box()
            min_z = bounds[0][2]
            max_z = bounds[1][2]
            if max_z == min_z:
                span = 0
            else:
                span = (len(texture)-1) / (max_z - min_z)    # max to avoid dividing by 0
            parts = P.partition(lambda x,y,z: int((z-min_z)*span))
        all = []
        for k, G in parts.iteritems():
            G.set_texture(texture[k], opacity=opacity)
            all.append(G)
        P = Graphics3dGroup(all)
    else:
        P.set_texture(texture)

    P.frame_aspect_ratio([1.0,1.0,0.5])
    P._set_extra_kwds(kwds)
    return P
Example #23
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 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 (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.

    - ``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))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x,y = var('x,y')
        g = density_plot(sin(x) * sin(y), (x,-2,2), (y,-2,2))
        sphinx_plot(g)

    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)
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x,y = var('x,y')
        def f(x,y): return x**2 * cos(x*y)
        g = density_plot(f, (x,-10,5), (y,-5,5), interpolation='sinc', plot_points=100)
        sphinx_plot(g)

    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)
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x,y = var('x,y')
        g = density_plot(sin(x**2 + y**2)*cos(x)*sin(y), (x,-4,4), (y,-4,4), cmap='jet', plot_points=100)
        sphinx_plot(g)

    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))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x,y = var('x,y')
        g = density_plot(1/(x**10 + y**10), (x,-10,10), (y,-10,10))
        sphinx_plot(g)

    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))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x,y = var('x,y')
        g = density_plot(y**2 + 1 - x**3 - x, (y,-pi,pi), (x,-pi,pi))
        sphinx_plot(g)

    ::

        sage: density_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x,y = var('x,y')
        g = density_plot(y**2 + 1 - x**3 - x, (x,-pi,pi), (y,-pi,pi))
        sphinx_plot(g)

    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)
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x,y = var('x,y')
        g = density_plot(log(x) + log(y), (x,1,10), (y,1,10), dpi=20)
        sphinx_plot(g)

    ::

        sage: density_plot(log(x) + log(y), (x,1,10), (y,1,10)).show(dpi=20) # These are equivalent

    TESTS:

    Check that :trac:`15315` is fixed, i.e., density_plot respects the
    ``aspect_ratio`` parameter. Without the fix, it looks like a thin line
    of width a few mm. With the fix it should look like a nice fat layered
    image::

        sage: density_plot((x*y)^(1/2), (x,0,3), (y,0,500), aspect_ratio=.01)
        Graphics object consisting of 1 graphics primitive

    Default ``aspect_ratio`` is ``"automatic"``, and that should work too::

        sage: density_plot((x*y)^(1/2), (x,0,3), (y,0,500))
        Graphics object consisting of 1 graphics primitive

    """
    from sage.plot.all 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
Example #24
0
def _parametric_plot3d_surface(f, urange, vrange, plot_points, boundary_style, **kwds):
    r"""
    Return a parametric three-dimensional space surface.
    This function is used internally by the
    :func:`parametric_plot3d` command.

    There are two ways this function is invoked by
    :func:`parametric_plot3d`.

    - ``parametric_plot3d([f_x, f_y, f_z], (u_min, u_max),
      (v_min, v_max))``:
      `f_x, f_y, f_z` are each functions of two variables

    - ``parametric_plot3d([f_x, f_y, f_z], (u, u_min,
      u_max), (v, v_min, v_max))``:
      `f_x, f_y, f_z` can be viewed as functions of
      `u` and `v`

    INPUT:

    - ``f`` - a 3-tuple of functions or expressions, or vector of size 3

    - ``urange`` - a 2-tuple (u_min, u_max) or a 3-tuple
      (u, u_min, u_max)

    - ``vrange`` - a 2-tuple (v_min, v_max) or a 3-tuple
      (v, v_min, v_max)

    - ``plot_points`` - (default: "automatic", which is [40,40]
      for surfaces) initial number of sample points in each parameter;
      a pair of integers.

    - ``boundary_style`` - (default: None, no boundary) a dict that describes
      how to draw the boundaries of regions by giving options that are passed
      to the line3d command.

    EXAMPLES:

    We demonstrate each of the two ways of calling this.  See
    :func:`parametric_plot3d` for many more examples.

    We do the first one with lambda functions::

        sage: f = (lambda u,v: cos(u), lambda u,v: sin(u)+cos(v), lambda u,v: sin(v))
        sage: parametric_plot3d(f, (0, 2*pi), (-pi, pi)) # indirect doctest
        Graphics3d Object

    Now we do the same thing with symbolic expressions::

        sage: u, v = var('u,v')
        sage: parametric_plot3d((cos(u), sin(u) + cos(v), sin(v)), (u, 0, 2*pi), (v, -pi, pi), mesh=True)
        Graphics3d Object
    """
    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid(f, [urange, vrange], plot_points)
    urange = srange(*ranges[0], include_endpoint=True)
    vrange = srange(*ranges[1], include_endpoint=True)
    G = ParametricSurface(g, (urange, vrange), **kwds)

    if boundary_style is not None:
        for u in (urange[0], urange[-1]):
            G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for v in vrange], **boundary_style)
        for v in (vrange[0], vrange[-1]):
            G += line3d([(g[0](u,v), g[1](u,v), g[2](u,v)) for u in urange], **boundary_style)
    return G
Example #25
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"``, ``"dotted"``, respectively ``"-"``, ``"--"``,
      ``"-."``, ``":"``.  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

    -  ``region`` - (default: None) If region is given, it must be a function
        of two variables. Only segments of the surface where region(x,y) returns a
        number >0 will be included in the plot.

    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))
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    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))
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi))
        Graphics object consisting of 1 graphics primitive

    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))
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(f, (-2, 2), (-2, 2), contours=2, cmap=[(1,0,0), (0,1,0), (0,0,1)])
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(f, (-2, 2), (-2, 2), contours=(0.1, 1.0, 1.2, 1.4), cmap='hsv')
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(f, (-2, 2), (-2, 2), contours=(1.0,), fill=False)
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(x-y^2,(x,-5,5),(y,-3,3),contours=[-4,0,1])
        Graphics object consisting of 1 graphics primitive

    We can change the style of the lines::

        sage: contour_plot(f, (-2,2), (-2,2), fill=False, linewidths=10)
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(f, (-2,2), (-2,2), fill=False, linestyles='dashdot')
        Graphics object consisting of 1 graphics primitive

    ::

        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
        Graphics object consisting of 1 graphics primitive

    ::

        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
        Graphics object consisting of 1 graphics primitive

        sage: P=contour_plot(x^2-y^2,(x,-3,3),(y,-3,3),contours=[0,1,2,3,4],\
        ...    linewidths=[1,5],linestyles=['-',':'])
        sage: P
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    ::

        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
        Graphics object consisting of 1 graphics primitive

    ::

        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
        Graphics object consisting of 1 graphics primitive

    ::

        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
        Graphics object consisting of 1 graphics primitive

    ::

        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
        Graphics object consisting of 1 graphics primitive

    ::

        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
        Graphics object consisting of 1 graphics primitive

    ::

        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
        Graphics object consisting of 1 graphics primitive

    We can change the color of the labels if so desired::

        sage: contour_plot(f, (-2,2), (-2,2), labels=True, label_colors='red')
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), colorbar=True,colorbar_orientation='horizontal')
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), contours=[-2,-1,4],colorbar=True)
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), contours=[-2,-1,4],colorbar=True,colorbar_spacing='uniform')
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), contours=[0,2,3,6],colorbar=True,colorbar_format='%.3f')
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), labels=True,label_colors='red',contours=[0,2,3,6],colorbar=True)
        Graphics object consisting of 1 graphics primitive

    ::

        sage: contour_plot(f, (x,-3,3), (y,-3,3), cmap='winter', contours=20, fill=False, colorbar=True)
        Graphics object consisting of 1 graphics primitive

    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))
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive

    One can also plot over a reduced region::

        sage: contour_plot(x**2-y**2, (x,-2, 2), (y,-2, 2),region=x-y,plot_points=300)
        Graphics object consisting of 1 graphics primitive

    ::

        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)
        Graphics object consisting of 1 graphics primitive

    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)
        Graphics object consisting of 1 graphics primitive
    """
    from sage.plot.all import Graphics
    from sage.plot.misc import setup_for_eval_on_grid

    region = options.pop('region')
    ev = [f] if region is None else [f, region]

    F, ranges = setup_for_eval_on_grid(ev, [xrange, yrange],
                                       options['plot_points'])
    g = F[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)]

    if region is not None:
        import numpy

        xy_data_array = numpy.ma.asarray(xy_data_array, dtype=float)

        m = F[1]

        mask = numpy.asarray([[
            m(x, y) <= 0 for x in xsrange(*ranges[0], include_endpoint=True)
        ] for y in xsrange(*ranges[1], include_endpoint=True)],
                             dtype=bool)

        xy_data_array[mask] = numpy.ma.masked

    g = Graphics()

    # Reset aspect_ratio to 'automatic' in case scale is 'semilog[xy]'.
    # Otherwise matplotlib complains.
    scale = options.get('scale', None)
    if isinstance(scale, (list, tuple)):
        scale = scale[0]
    if scale == 'semilogy' or scale == 'semilogx':
        options['aspect_ratio'] = 'automatic'

    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
Example #26
0
def plot3d_adaptive(f,
                    x_range,
                    y_range,
                    color="automatic",
                    grad_f=None,
                    max_bend=.5,
                    max_depth=5,
                    initial_depth=4,
                    num_colors=128,
                    **kwds):
    r"""
    Adaptive 3d plotting of a function of two variables.

    This is used internally by the plot3d command when the option
    ``adaptive=True`` is given.

    INPUT:


    -  ``f`` - a symbolic function or a Python function of
       3 variables.

    -  ``x_range`` - x range of values: 2-tuple (xmin,
       xmax) or 3-tuple (x,xmin,xmax)

    -  ``y_range`` - y range of values: 2-tuple (ymin,
       ymax) or 3-tuple (y,ymin,ymax)

    -  ``grad_f`` - gradient of f as a Python function

    -  ``color`` - "automatic" - a rainbow of num_colors
       colors

    -  ``num_colors`` - (default: 128) number of colors to
       use with default color

    -  ``max_bend`` - (default: 0.5)

    -  ``max_depth`` - (default: 5)

    -  ``initial_depth`` - (default: 4)

    -  ``**kwds`` - standard graphics parameters


    EXAMPLES:

    We plot `\sin(xy)`::

        sage: from sage.plot.plot3d.plot3d import plot3d_adaptive
        sage: x,y=var('x,y'); plot3d_adaptive(sin(x*y), (x,-pi,pi), (y,-pi,pi), initial_depth=5)
        Graphics3d Object
        
    .. PLOT::
        
        from sage.plot.plot3d.plot3d import plot3d_adaptive
        x,y=var('x,y')
        sphinx_plot(plot3d_adaptive(sin(x*y), (x,-pi,pi), (y,-pi,pi), initial_depth=5))

    """
    if initial_depth >= max_depth:
        max_depth = initial_depth

    from sage.plot.misc import setup_for_eval_on_grid
    g, ranges = setup_for_eval_on_grid(f, [x_range, y_range], plot_points=2)
    xmin, xmax = ranges[0][:2]
    ymin, ymax = ranges[1][:2]

    opacity = kwds.get('opacity', 1)

    if color == "automatic":
        texture = rainbow(num_colors, 'rgbtuple')
    else:
        if isinstance(color, list):
            texture = color
        else:
            kwds['color'] = color
            texture = Texture(kwds)

    factory = TrivialTriangleFactory()
    plot = TrianglePlot(factory,
                        g, (xmin, xmax), (ymin, ymax),
                        g=grad_f,
                        min_depth=initial_depth,
                        max_depth=max_depth,
                        max_bend=max_bend,
                        num_colors=None)

    P = IndexFaceSet(plot._objects)
    if isinstance(texture, (list, tuple)):
        if len(texture) == 2:
            # do a grid coloring
            xticks = (xmax - xmin) / 2**initial_depth
            yticks = (ymax - ymin) / 2**initial_depth
            parts = P.partition(lambda x, y, z: (int(
                (x - xmin) / xticks) + int((y - ymin) / yticks)) % 2)
        else:
            # do a topo coloring
            bounds = P.bounding_box()
            min_z = bounds[0][2]
            max_z = bounds[1][2]
            if max_z == min_z:
                span = 0
            else:
                span = (len(texture) - 1) / (max_z - min_z
                                             )  # max to avoid dividing by 0
            parts = P.partition(lambda x, y, z: int((z - min_z) * span))
        all = []
        for k, G in iteritems(parts):
            G.set_texture(texture[k], opacity=opacity)
            all.append(G)
        P = Graphics3dGroup(all)
    else:
        P.set_texture(texture)

    P.frame_aspect_ratio([1.0, 1.0, 0.5])
    P._set_extra_kwds(kwds)
    return P
Example #27
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.all 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
Example #28
0
def streamline_plot(f_g, xrange, yrange, **options):
    r"""
    Return a streamline plot in a vector field.

    ``streamline_plot`` can take either one or two functions. Consider
    two variables `x` and `y`.

    If given two functions `(f(x,y), g(x,y))`, then this function plots
    streamlines in the vector field over the specified ranges with ``xrange``
    being of `x`, denoted by ``xvar`` below, between ``xmin`` and ``xmax``,
    and ``yrange`` similarly (see below). ::

        streamline_plot((f, g), (xvar, xmin, xmax), (yvar, ymin, ymax))

    Similarly, if given one function `f(x, y)`, then this function plots
    streamlines in the slope field `dy/dx = f(x,y)` over the specified
    ranges as given above.

    PLOT OPTIONS:

    - ``plot_points`` -- (default: 200) the minimal number of plot points

    - ``density`` -- float (default: 1.); controls the closeness of
      streamlines

    - ``start_points`` -- (optional) list of coordinates of starting
      points for the streamlines; coordinate pairs can be tuples or lists

    EXAMPLES:

    Plot some vector fields involving `\sin` and `\cos`::

        sage: x, y = var('x y')
        sage: streamline_plot((sin(x), cos(y)), (x,-3,3), (y,-3,3))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((sin(x), cos(y)), (x,-3,3), (y,-3,3))
        sphinx_plot(g)

    ::

        sage: streamline_plot((y, (cos(x)-2) * sin(x)), (x,-pi,pi), (y,-pi,pi))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((y, (cos(x)-2) * sin(x)), (x,-pi,pi), (y,-pi,pi))
        sphinx_plot(g)

    We increase the density of the plot::

        sage: streamline_plot((y, (cos(x)-2) * sin(x)), (x,-pi,pi), (y,-pi,pi), density=2)
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((y, (cos(x)-2) * sin(x)), (x,-pi,pi), (y,-pi,pi), density=2)
        sphinx_plot(g)

    We ignore function values that are infinite or NaN::

        sage: x, y = var('x y')
        sage: streamline_plot((-x/sqrt(x^2+y^2), -y/sqrt(x^2+y^2)), (x,-10,10), (y,-10,10))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((-x/sqrt(x**2+y**2), -y/sqrt(x**2+y**2)), (x,-10,10), (y,-10,10))
        sphinx_plot(g)

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

        sage: streamline_plot((x, y), (x,-2,2), (y,-2,2), xmax=10)
        Graphics object consisting of 1 graphics primitive
        sage: streamline_plot((x, y), (x,-2,2), (y,-2,2)).show(xmax=10) # These are equivalent

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((x, y), (x,-2,2), (y,-2,2), xmax=10)
        sphinx_plot(g)

    We can also construct streamlines in a slope field::

        sage: x, y = var('x y')
        sage: streamline_plot((x + y) / sqrt(x^2 + y^2), (x,-3,3), (y,-3,3))
        Graphics object consisting of 1 graphics primitive

    .. PLOT::

        x, y = var('x y')
        g = streamline_plot((x + y) / sqrt(x**2 + y**2), (x,-3,3), (y,-3,3))
        sphinx_plot(g)

    We choose some particular points the streamlines pass through::

        sage: pts = [[1, 1], [-2, 2], [1, -3/2]]
        sage: g = streamline_plot((x + y) / sqrt(x^2 + y^2), (x,-3,3), (y,-3,3), start_points=pts)
        sage: g += point(pts, color='red')
        sage: g
        Graphics object consisting of 2 graphics primitives

    .. PLOT::

        x, y = var('x y')
        pts = [[1, 1], [-2, 2], [1, -3/2]]
        g = streamline_plot((x + y) / sqrt(x**2 + y**2), (x,-3,3), (y,-3,3), start_points=pts)
        g += point(pts, color='red')
        sphinx_plot(g)

    .. NOTE::

        Streamlines currently pass close to ``start_points`` but do
        not necessarily pass directly through them. That is part of
        the behavior of matplotlib, not an error on your part.

    """
    # Parse the function input
    if isinstance(f_g, (list, tuple)):
        (f,g) = f_g
    else:
        from sage.functions.all import sqrt
        from inspect import isfunction
        if isfunction(f_g):
            f = lambda x,y: 1 / sqrt(f_g(x, y)**2 + 1)
            g = lambda x,y: f_g(x, y) * f(x, y)
        else:
            f = 1 / sqrt(f_g**2 + 1)
            g = f_g * f

    from sage.plot.all import Graphics
    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

    # The density values must be floats
    if isinstance(options['density'], (list, tuple)):
        options['density'] = [float(x) for x in options['density']]
    else:
        options['density'] = float(options['density'])

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

    import numpy
    xpos_array = numpy.array(xpos_array, dtype=float)
    ypos_array = numpy.array(ypos_array, dtype=float)
    xvec_array = numpy.ma.masked_invalid(numpy.array(xvec_array, dtype=float))
    yvec_array = numpy.ma.masked_invalid(numpy.array(yvec_array, dtype=float))

    if 'start_points' in options:
        xstart_array, ystart_array = [], []
        for point in options['start_points']:
            xstart_array.append(point[0])
            ystart_array.append(point[1])
        options['start_points'] = numpy.array([xstart_array, ystart_array]).T

    g = Graphics()
    g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
    g.add_primitive(StreamlinePlot(xpos_array, ypos_array,
                                   xvec_array, yvec_array, options))
    return g