예제 #1
0
def list_plot3d_matrix(m, texture, **kwds):
    from parametric_surface import ParametricSurface

    f = lambda i, j: (i, j, float(m[int(i), int(j)]))
    G = ParametricSurface(f, (range(m.nrows()), range(m.ncols())), texture=texture, **kwds)
    G._set_extra_kwds(kwds)
    return G
예제 #2
0
def list_plot3d_matrix(m, texture, **kwds):
    from parametric_surface import ParametricSurface
    f = lambda i, j: (i, j, float(m[int(i), int(j)]))
    G = ParametricSurface(f, (range(m.nrows()), range(m.ncols())),
                          texture=texture,
                          **kwds)
    G._set_extra_kwds(kwds)
    return G
예제 #3
0
def list_plot3d_matrix(m, texture, **kwds):
    """
    A 3-dimensional plot of a surface defined by a matrix ``M``
    defining points in 3-dimensional space.  See :func:`list_plot3d`
    for full details.

    INPUT:

    - ``M`` - a matrix
    - ``texture`` - (default: "automatic", a solid light blue)

    OPTIONAL KEYWORDS:

    - ``**kwds`` - all other arguments are passed to the
       surface function

    OUTPUT: a 3d plot

    EXAMPLES:

    We plot a matrix that illustrates summation modulo `n`::

        sage: n = 5; list_plot3d(matrix(RDF,n,[(i+j)%n for i in [1..n] for j in [1..n]])) # indirect doctest
        Graphics3d Object

    The interpolation type for matrices is 'linear'; for other types
    use other :func:`list_plot3d` input types.

    We plot a matrix of values of `sin`::

        sage: pi = float(pi)
        sage: m = matrix(RDF, 6, [sin(i^2 + j^2) for i in [0,pi/5,..,pi] for j in [0,pi/5,..,pi]])
        sage: list_plot3d(m, texture='yellow', frame_aspect_ratio=[1,1,1/3]) # indirect doctest
        Graphics3d Object
        sage: list_plot3d(m, texture='yellow', interpolation_type='linear') # indirect doctest
        Graphics3d Object
    """
    from parametric_surface import ParametricSurface
    f = lambda i, j: (i, j, float(m[int(i), int(j)]))
    G = ParametricSurface(f, (range(m.nrows()), range(m.ncols())),
                          texture=texture,
                          **kwds)
    G._set_extra_kwds(kwds)
    return G
예제 #4
0
def list_plot3d_matrix(m, texture, **kwds):
    """
    A 3-dimensional plot of a surface defined by a matrix ``M``
    defining points in 3-dimensional space.  See :func:`list_plot3d`
    for full details.

    INPUT:

    - ``M`` - a matrix
    - ``texture`` - (default: "automatic", a solid light blue)

    OPTIONAL KEYWORDS:

    - ``**kwds`` - all other arguments are passed to the
       surface function

    OUTPUT: a 3d plot

    EXAMPLES:

    We plot a matrix that illustrates summation modulo `n`::

        sage: n = 5; list_plot3d(matrix(RDF, n, [(i+j)%n for i in [1..n] for j in [1..n]])) # indirect doctest
        Graphics3d Object

    The interpolation type for matrices is 'linear'; for other types
    use other :func:`list_plot3d` input types.

    We plot a matrix of values of `sin`::

        sage: pi = float(pi)
        sage: m = matrix(RDF, 6, [sin(i^2 + j^2) for i in [0,pi/5,..,pi] for j in [0,pi/5,..,pi]])
        sage: list_plot3d(m, texture='yellow', frame_aspect_ratio=[1, 1, 1/3]) # indirect doctest
        Graphics3d Object
        sage: list_plot3d(m, texture='yellow', interpolation_type='linear') # indirect doctest
        Graphics3d Object
    """
    from parametric_surface import ParametricSurface
    f = lambda i,j: (i, j, float(m[int(i), int(j)]))
    G = ParametricSurface(f, (range(m.nrows()), range(m.ncols())), texture=texture, **kwds)
    G._set_extra_kwds(kwds)
    return G
예제 #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
예제 #6
0
def list_plot3d_tuples(v, interpolation_type, texture, **kwds):
    r"""
    A 3-dimensional plot of a surface defined by the list `v`
    of points in 3-dimensional space.

    INPUT:

    - ``v`` - something that defines a set of points in 3
      space, for example:

      - a matrix

        This will be if using an interpolation type other than 'linear', or if using
        ``num_points`` with 'linear'; otherwise see :func:`list_plot3d_matrix`.

      - a list of 3-tuples

      - a list of lists (all of the same length, under same conditions as a matrix)

    - ``texture`` - (default: "automatic", a solid light blue)

    OPTIONAL KEYWORDS:

    - ``interpolation_type`` - 'linear', 'nn' (natural neighbor), 'spline'

      'linear' will perform linear interpolation

      The option 'nn' will interpolate by using natural neighbors. The 
      value for an interpolation point is estimated using weighted values 
      of the closest surrounding points in the triangulation.

      The option 'spline' interpolates using a bivariate B-spline.

      When v is a matrix the default is to use linear interpolation, when
      v is a list of points the default is nearest neighbor.

    - ``degree`` - an integer between 1 and 5, controls the degree of spline
      used for spline interpolation. For data that is highly oscillatory
      use higher values

    - ``point_list`` - If point_list=True is passed, then if the array
      is a list of lists of length three, it will be treated as an
      array of points rather than a `3\times n` array.

    - ``num_points`` - Number of points to sample interpolating
      function in each direction.  By default for an `n\times n`
      array this is `n`.

    - ``**kwds`` - all other arguments are passed to the
      surface function

    OUTPUT: a 3d plot

    EXAMPLES:

    All of these use this function; see :func:`list_plot3d` for other list plots::

        sage: pi = float(pi)
        sage: m = matrix(RDF, 6, [sin(i^2 + j^2) for i in [0,pi/5,..,pi] for j in [0,pi/5,..,pi]])
        sage: list_plot3d(m, texture='yellow', interpolation_type='linear', num_points=5) # indirect doctest
        Graphics3d Object

    ::

        sage: list_plot3d(m, texture='yellow', interpolation_type='spline', frame_aspect_ratio=[1, 1, 1/3])
        Graphics3d Object

    ::

        sage: show(list_plot3d([[1, 1, 1], [1, 2, 1], [0, 1, 3], [1, 0, 4]], point_list=True))

    ::

        sage: list_plot3d([(1, 2, 3), (0, 1, 3), (2, 1, 4), (1, 0, -2)], texture='yellow', num_points=50)
        Graphics3d Object
    """
    from matplotlib import tri, delaunay
    import numpy
    import scipy
    from random import random
    from scipy import interpolate
    from plot3d import plot3d

    if len(v)<3:
        raise ValueError("We need at least 3 points to perform the interpolation")

    x = [float(p[0]) for p in v]
    y = [float(p[1]) for p in v]
    z = [float(p[2]) for p in v]

    # If the (x,y)-coordinates lie in a one-dimensional subspace, the
    # matplotlib Delaunay code segfaults.  Therefore, we compute the
    # correlation of the x- and y-coordinates and add small random
    # noise to avoid the problem if needed.
    corr_matrix = numpy.corrcoef(x, y)
    if corr_matrix[0, 1] > 0.9 or corr_matrix[0, 1] < -0.9:
        ep = float(.000001)
        x = [float(p[0]) + random()*ep for p in v]
        y = [float(p[1]) + random()*ep for p in v]


    # If the list of data points has two points with the exact same
    # (x,y)-coordinate but different z-coordinates, then we sometimes
    # get segfaults.  The following block checks for this and raises
    # an exception if this is the case.
    # We also remove duplicate points (which matplotlib can't handle).
    # Alternatively, the code in the if block above which adds random
    # error could be applied to perturb the points.
    drop_list = []
    nb_points = len(x)
    for i in range(nb_points):
        for j in range(i+1, nb_points):
            if x[i] == x[j] and y[i] == y[j]:
                if z[i] != z[j]:
                    raise ValueError("Two points with same x,y coordinates and different z coordinates were given. Interpolation cannot handle this.")
                elif z[i] == z[j]:
                    drop_list.append(j)
    x = [x[i] for i in range(nb_points) if i not in drop_list]
    y = [y[i] for i in range(nb_points) if i not in drop_list]
    z = [z[i] for i in range(nb_points) if i not in drop_list]

    xmin = float(min(x))
    xmax = float(max(x))
    ymin = float(min(y))
    ymax = float(max(y))

    num_points = kwds['num_points'] if 'num_points' in kwds else int(4*numpy.sqrt(len(x)))
                                          #arbitrary choice - assuming more or less a nxn grid of points
                                          # x should have n^2 entries. We sample 4 times that many points.

    if interpolation_type == 'linear':
        T = tri.Triangulation(x, y)
        f = tri.LinearTriInterpolator(T, z)
        j = numpy.complex(0, 1)
        from parametric_surface import ParametricSurface
        def g(x, y):
            z = f(x, y)
            return (x, y, z)
        G = ParametricSurface(g, (list(numpy.r_[xmin:xmax:num_points*j]), list(numpy.r_[ymin:ymax:num_points*j])), texture=texture, **kwds)
        G._set_extra_kwds(kwds)
        return G

    if interpolation_type == 'nn'  or interpolation_type =='default':

        T=delaunay.Triangulation(x,y)
        f=T.nn_interpolator(z)
        f.default_value=0.0
        j=numpy.complex(0,1)
        vals=f[ymin:ymax:j*num_points,xmin:xmax:j*num_points]
        from parametric_surface import ParametricSurface
        def g(x,y):
            i=round( (x-xmin)/(xmax-xmin)*(num_points-1) )
            j=round( (y-ymin)/(ymax-ymin)*(num_points-1) )
            z=vals[int(j),int(i)]
            return (x,y,z)
        G = ParametricSurface(g, (list(numpy.r_[xmin:xmax:num_points*j]), list(numpy.r_[ymin:ymax:num_points*j])), texture=texture, **kwds)
        G._set_extra_kwds(kwds)
        return G

    if interpolation_type == 'spline':
        from plot3d import plot3d
        kx = kwds['kx'] if 'kx' in kwds else 3
        ky = kwds['ky'] if 'ky' in kwds else 3
        if 'degree' in kwds:
            kx = kwds['degree']
            ky = kwds['degree']
        s = kwds['smoothing'] if 'smoothing' in kwds else len(x)-numpy.sqrt(2*len(x))
        s = interpolate.bisplrep(x, y, z, [int(1)]*len(x), xmin, xmax, ymin, ymax, kx=kx, ky=ky, s=s)
        f = lambda x,y: interpolate.bisplev(x, y, s)
        return plot3d(f, (xmin, xmax), (ymin, ymax), texture=texture, plot_points=[num_points, num_points], **kwds)
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

    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)
    """
    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
예제 #8
0
def list_plot3d_tuples(v, interpolation_type, texture, **kwds):
    from matplotlib import delaunay
    import numpy
    import scipy
    from random import random
    from scipy import interpolate
    from plot3d import plot3d

    if len(v) < 3:
        raise ValueError, "We need at least 3 points to perform the interpolation"

    x = [float(p[0]) for p in v]
    y = [float(p[1]) for p in v]
    z = [float(p[2]) for p in v]

    corr_matrix = numpy.corrcoef(x, y)

    if corr_matrix[0, 1] > .9 or corr_matrix[0, 1] < -.9:
        # If the x,y coordinates lie in a one-dimensional subspace
        # The scipy delauney code segfaults
        # We compute the correlation of the x and y coordinates
        # and add small random noise to avoid the problem
        # if it looks like there is an issue

        ep = float(.000001)
        x = [float(p[0]) + random() * ep for p in v]
        y = [float(p[1]) + random() * ep for p in v]

    #If the list of data points has two points with the exact same x,y coordinate and different z coordinates
    #then scipy sometimes segfaults. The following block checks for this. alternatively the code in the if block
    #above which adds random error could be applied to perturb the points, but probably an exception should be raised
    #The code also removes duplicate points which scipy can't handle.

    drop_list = []

    for i in range(len(x)):
        for j in range(i + 1, len(x)):
            if x[i] == x[j] and y[i] == y[j]:
                if z[i] != z[j]:
                    raise ValueError, "Two points with same x,y coordinates and different z coordinates were given. Interpolation cannot handle this."
                elif z[i] == z[j]:
                    drop_list.append(j)

    x = [x[i] for i in range(len(x)) if i not in drop_list]
    y = [y[i] for i in range(len(x)) if i not in drop_list]
    z = [z[i] for i in range(len(x)) if i not in drop_list]

    xmin = float(min(x))
    xmax = float(max(x))
    ymin = float(min(y))
    ymax = float(max(y))

    num_points = kwds['num_points'] if kwds.has_key('num_points') else int(
        4 * numpy.sqrt(len(x)))
    #arbitrary choice - assuming more or less a nxn grid of points
    # x should have n^2 entries. We sample 4 times that many points.

    if interpolation_type == 'linear':

        T = delaunay.Triangulation(x, y)
        f = T.linear_interpolator(z)
        f.default_value = 0.0
        j = numpy.complex(0, 1)
        vals = f[ymin:ymax:j * num_points, xmin:xmax:j * num_points]
        from parametric_surface import ParametricSurface

        def g(x, y):
            i = round((x - xmin) / (xmax - xmin) * (num_points - 1))
            j = round((y - ymin) / (ymax - ymin) * (num_points - 1))
            z = vals[int(j), int(i)]
            return (x, y, z)

        G = ParametricSurface(g, (list(numpy.r_[xmin:xmax:num_points * j]),
                                  list(numpy.r_[ymin:ymax:num_points * j])),
                              texture=texture,
                              **kwds)
        G._set_extra_kwds(kwds)
        return G

    if interpolation_type == 'nn' or interpolation_type == 'default':

        T = delaunay.Triangulation(x, y)
        f = T.nn_interpolator(z)
        f.default_value = 0.0
        j = numpy.complex(0, 1)
        vals = f[ymin:ymax:j * num_points, xmin:xmax:j * num_points]
        from parametric_surface import ParametricSurface

        def g(x, y):
            i = round((x - xmin) / (xmax - xmin) * (num_points - 1))
            j = round((y - ymin) / (ymax - ymin) * (num_points - 1))
            z = vals[int(j), int(i)]
            return (x, y, z)

        G = ParametricSurface(g, (list(numpy.r_[xmin:xmax:num_points * j]),
                                  list(numpy.r_[ymin:ymax:num_points * j])),
                              texture=texture,
                              **kwds)
        G._set_extra_kwds(kwds)
        return G

    if interpolation_type == 'spline':
        from plot3d import plot3d
        kx = kwds['kx'] if kwds.has_key('kx') else 3
        ky = kwds['ky'] if kwds.has_key('ky') else 3
        if kwds.has_key('degree'):
            kx = kwds['degree']
            ky = kwds['degree']

        s = kwds['smoothing'] if kwds.has_key(
            'smoothing') else len(x) - numpy.sqrt(2 * len(x))
        s = interpolate.bisplrep(x,
                                 y,
                                 z, [int(1)] * len(x),
                                 xmin,
                                 xmax,
                                 ymin,
                                 ymax,
                                 kx=kx,
                                 ky=ky,
                                 s=s)
        f = lambda x, y: interpolate.bisplev(x, y, s)
        return plot3d(f, (xmin, xmax), (ymin, ymax),
                      texture=texture,
                      plot_points=[num_points, num_points],
                      **kwds)
예제 #9
0
def list_plot3d_tuples(v, interpolation_type, texture, **kwds):
    from matplotlib import delaunay
    import numpy
    import scipy
    from random import random
    from scipy import interpolate
    from plot3d import plot3d

    if len(v) < 3:
        raise ValueError, "We need at least 3 points to perform the interpolation"

    x = [float(p[0]) for p in v]
    y = [float(p[1]) for p in v]
    z = [float(p[2]) for p in v]

    corr_matrix = numpy.corrcoef(x, y)

    if corr_matrix[0, 1] > 0.9 or corr_matrix[0, 1] < -0.9:
        # If the x,y coordinates lie in a one-dimensional subspace
        # The scipy delauney code segfaults
        # We compute the correlation of the x and y coordinates
        # and add small random noise to avoid the problem
        # if it looks like there is an issue

        ep = float(0.000001)
        x = [float(p[0]) + random() * ep for p in v]
        y = [float(p[1]) + random() * ep for p in v]

    # If the list of data points has two points with the exact same x,y coordinate and different z coordinates
    # then scipy sometimes segfaults. The following block checks for this. alternatively the code in the if block
    # above which adds random error could be applied to perturb the points, but probably an exception should be raised
    # The code also removes duplicate points which scipy can't handle.

    drop_list = []

    for i in range(len(x)):
        for j in range(i + 1, len(x)):
            if x[i] == x[j] and y[i] == y[j]:
                if z[i] != z[j]:
                    raise ValueError, "Two points with same x,y coordinates and different z coordinates were given. Interpolation cannot handle this."
                elif z[i] == z[j]:
                    drop_list.append(j)

    x = [x[i] for i in range(len(x)) if i not in drop_list]
    y = [y[i] for i in range(len(x)) if i not in drop_list]
    z = [z[i] for i in range(len(x)) if i not in drop_list]

    xmin = float(min(x))
    xmax = float(max(x))
    ymin = float(min(y))
    ymax = float(max(y))

    num_points = kwds["num_points"] if kwds.has_key("num_points") else int(4 * numpy.sqrt(len(x)))
    # arbitrary choice - assuming more or less a nxn grid of points
    # x should have n^2 entries. We sample 4 times that many points.

    if interpolation_type == "linear":

        T = delaunay.Triangulation(x, y)
        f = T.linear_interpolator(z)
        f.default_value = 0.0
        j = numpy.complex(0, 1)
        vals = f[ymin : ymax : j * num_points, xmin : xmax : j * num_points]
        from parametric_surface import ParametricSurface

        def g(x, y):
            i = round((x - xmin) / (xmax - xmin) * (num_points - 1))
            j = round((y - ymin) / (ymax - ymin) * (num_points - 1))
            z = vals[int(j), int(i)]
            return (x, y, z)

        G = ParametricSurface(
            g,
            (list(numpy.r_[xmin : xmax : num_points * j]), list(numpy.r_[ymin : ymax : num_points * j])),
            texture=texture,
            **kwds
        )
        G._set_extra_kwds(kwds)
        return G

    if interpolation_type == "nn" or interpolation_type == "default":

        T = delaunay.Triangulation(x, y)
        f = T.nn_interpolator(z)
        f.default_value = 0.0
        j = numpy.complex(0, 1)
        vals = f[ymin : ymax : j * num_points, xmin : xmax : j * num_points]
        from parametric_surface import ParametricSurface

        def g(x, y):
            i = round((x - xmin) / (xmax - xmin) * (num_points - 1))
            j = round((y - ymin) / (ymax - ymin) * (num_points - 1))
            z = vals[int(j), int(i)]
            return (x, y, z)

        G = ParametricSurface(
            g,
            (list(numpy.r_[xmin : xmax : num_points * j]), list(numpy.r_[ymin : ymax : num_points * j])),
            texture=texture,
            **kwds
        )
        G._set_extra_kwds(kwds)
        return G

    if interpolation_type == "spline":
        from plot3d import plot3d

        kx = kwds["kx"] if kwds.has_key("kx") else 3
        ky = kwds["ky"] if kwds.has_key("ky") else 3
        if kwds.has_key("degree"):
            kx = kwds["degree"]
            ky = kwds["degree"]

        s = kwds["smoothing"] if kwds.has_key("smoothing") else len(x) - numpy.sqrt(2 * len(x))
        s = interpolate.bisplrep(x, y, z, [int(1)] * len(x), xmin, xmax, ymin, ymax, kx=kx, ky=ky, s=s)
        f = lambda x, y: interpolate.bisplev(x, y, s)
        return plot3d(f, (xmin, xmax), (ymin, ymax), texture=texture, plot_points=[num_points, num_points], **kwds)