# source:sage/plot/plot3d/list_plot3d.py@8222:d32ba0ce79ea

Revision 8222:d32ba0ce79ea, 8.8 KB checked in by mabshoff@…, 5 years ago (diff)

merge

Line
1"""
2List Plots
3"""
4
5from sage.matrix.all import is_Matrix, matrix
6from sage.rings.all  import RDF
7
8def list_plot3d(v, interpolation_type='default', texture="automatic", point_list=None,**kwds):
9    """
10    A 3-dimensional plot of a surface defined by the list \$v\$ of
11    points in 3-dimensional space.
12
13    INPUT:
14        v -- something that defines a set of points in 3 space,
15             for example:
16                 * a matrix
17                 * a list of 3-tuples
18                 * a list of lists (all of the same length) -- this
19                   is treated the same as a matrix.
20        texture -- (default: "automatic"), solid light blue
21
22    OPTIONAL KEYWORDS:
23
24        interpolation_type - 'linear', 'nn' (nearest neighbor), 'spline'
25
26             'linear'  will perform linear interpolation
27
28             The option 'nn' will interpolate by averaging the value
29             of the nearest neighbors, this produces an interpolating function that is smoother than a linear interpolation, it
30             has one derivative everywhere except at the sample points.
31
32             The option 'spline' interpolates using a bivariate B-spline.
33
34             When v is a matrix the default is to use linear interpolation,
35             when v is a list of points the default is nearest neighbor.
36
37        degree - an integer between 1 and 5, controls the degree of spline
38             used for spline interpolation. For data that is highly oscillatory
39             use higher values
40
41        point_list - If point_list=True is passed, then if the array is a
42             list of lists of length three, it will be treated  as an array of
43             points rather than a 3xn array.
44
45        num_points - Number of points to sample interpolating function in each direction. By default
46                     for an nxn array this is n.
47
48
49        **kwds -- all other arguments are passed to the surface function
50
51    OUTPUT:
52        a 3d plot
53
54    EXAMPLES:
55    We plot a matrix that illustrates summation modulo \$n\$.
56        sage: n = 5; list_plot3d(matrix(RDF,n,[(i+j)%n for i in [1..n] for j in [1..n]]))
57
58    We plot a matrix of values of sin.
59        sage: pi = float(pi)
60        sage: m = matrix(RDF, 6, [sin(i^2 + j^2) for i in [0,pi/5,..,pi] for j in [0,pi/5,..,pi]])
61        sage: list_plot3d(m, texture='yellow', frame_aspect_ratio=[1,1,1/3])
62
63   Though it doesn't change the shap of the graph, increasing num_points can increase the clarity of the
64   graph
65        sage: list_plot3d(m, texture='yellow', frame_aspect_ratio=[1,1,1/3],num_points=40)
66
67    We can change the interpolation type
68        sage: list_plot3d(m, texture='yellow', interpolation_type='nn',frame_aspect_ratio=[1,1,1/3])
69
70    We can make this look better by increasing the number of samples
71        sage: list_plot3d(m, texture='yellow', interpolation_type='nn',frame_aspect_ratio=[1,1,1/3],num_points=40)
72
73    Lets try a spline
74        sage: list_plot3d(m, texture='yellow', interpolation_type='spline',frame_aspect_ratio=[1,1,1/3])
75
76    That spline doesn't capture the oscillation very well, lets try a higher degree spline
77        sage: list_plot3d(m, texture='yellow', interpolation_type='spline', degree=5, frame_aspect_ratio=[1,1,1/3])
78
79
80    We plot a list of lists:
81        sage: show(list_plot3d([[1, 1, 1, 1], [1, 2, 1, 2], [1, 1, 3, 1], [1, 2, 1, 4]]))
82
83    We plot a list of points:
84        As a first example  we can extract the (x,y,z) coordinates from the above example and
85        make a list plot out of it. By default we do linear interpolation.
86
87        sage: l=[]
88        sage: for i in range(6):
89        ...      for j in range(6):
90        ...         l.append((float(i*pi/5),float(j*pi/5),m[i,j]))
91        sage: list_plot3d(l,texture='yellow')
92
93
94        Note that the points do not have to be regularly sampled. For example
95
96        sage: l=[]
97        sage: T=Random()
98        sage: for i in range(-5,5)
99        ...    for j in range(-5,5)
100        ...      l.append((T.normalvariate(0,1),T.normalvariate(0,1),T.normalvariate(0,1)))
101        sage: list_plot3d(l,interpolation_type='nn',texture='yellow',num_points=100)
102
103
104    """
105    import numpy
106    if texture == "automatic":
107        texture = "lightblue"
108    if is_Matrix(v):
109        if interpolation_type=='default' or interpolation_type=='linear' and not kwds.has_key('num_points'):
110            return list_plot3d_matrix(v, texture=texture,  **kwds)
111        else:
112            l=[]
113            for i in xrange(v.nrows()):
114                for j in xrange(v.ncols()):
115                    l.append((i,j,v[i,j]))
116            return list_plot3d_tuples(l,interpolation_type,texture,**kwds)
117
118    if type(v)==numpy.ndarray:
119        return list_plot3d(matrix(v),interpolation_type,texture,**kwds)
120
121    if isinstance(v, list):
122        if len(v) == 0:
123            # return empty 3d graphic
124            from base import Graphics3d
125            return Graphics3d()
126        elif isinstance(v[0],tuple) or point_list==True and len(v[0]) == 3:
127            return list_plot3d_tuples(v,interpolation_type,texture=texture, **kwds)
128        else:
129            return list_plot3d_array_of_arrays(v, interpolation_type,texture, **kwds)
130    raise TypeError, "v must be a matrix or list"
131
132def list_plot3d_matrix(m, texture, **kwds):
133    from parametric_surface import ParametricSurface
134    f = lambda i,j: (i,j,float(m[int(i),int(j)]))
135    G = ParametricSurface(f, (range(m.nrows()), range(m.ncols())), texture=texture, **kwds)
136    G._set_extra_kwds(kwds)
137    return G
138
139def list_plot3d_array_of_arrays(v, interpolation_type,texture, **kwds):
140    m = matrix(RDF, len(v), len(v[0]), v)
141    G = list_plot3d(m,interpolation_type,texture, **kwds)
142    G._set_extra_kwds(kwds)
143    return G
144
145def list_plot3d_tuples(v,interpolation_type, texture, **kwds):
146    import delaunay
147    import numpy
148    import scipy
149    from random import random
150    from scipy import interpolate
151    from scipy import stats
152    from plot3d import plot3d
153
154    x=[float(p[0]) for p in v]
155    y=[float(p[1]) for p in v]
156    z=[float(p[2]) for p in v]
157
158    corr_matrix=stats.corrcoef(x,y)
159
160    if corr_matrix[0,1] > .9 or corr_matrix[0,1] <  -.9:
161        # If the x,y coordinates lie in a one-dimensional subspace
162        # The scipy delauney code segfaults
163        # We compute the correlation of the x and y coordinates
164        # and add small random noise to avoid the problem
165        # if it looks like there is an issue
166
167        ep=float(.000001)
168        x=[float(p[0])+random()*ep for p in v]
169        y=[float(p[1])+random()*ep for p in v]
170
171
172    xmin=float(min(x))
173    xmax=float(max(x))
174    ymin=float(min(y))
175    ymax=float(max(y))
176
177    num_points= kwds['num_points'] if kwds.has_key('num_points') else int(4*numpy.sqrt(len(x)))
178                                          #arbitrary choice - assuming more or less a nxn grid of points
179                                          # x should have n^2 entries. We sample 4 times that many points.
180
181
182
183    if interpolation_type == 'linear':
184
185        T= delaunay.Triangulation(x,y)
186        f=T.linear_interpolator(z)
187        f.default_value=0.0
188        j=numpy.complex(0,1)
189        vals=f[ymin:ymax:j*num_points,xmin:xmax:j*num_points]
190        from parametric_surface import ParametricSurface
191
192        def g(x,y):
193            i=round( (x-xmin)/(xmax-xmin)*(num_points-1) )
194            j=round( (y-ymin)/(ymax-ymin)*(num_points-1) )
195            z=vals[int(j),int(i)]
196            return (x,y,z)
197
198
199        G = ParametricSurface(g, (list(numpy.r_[xmin:xmax:num_points*j]), list(numpy.r_[ymin:ymax:num_points*j])), texture=texture, **kwds)
200        G._set_extra_kwds(kwds)
201        return G
202
203
204    if interpolation_type == 'nn'  or interpolation_type =='default':
205
206        T=delaunay.Triangulation(x,y)
207        f=T.nn_interpolator(z)
208        f.default_value=0.0
209        j=numpy.complex(0,1)
210        vals=f[ymin:ymax:j*num_points,xmin:xmax:j*num_points]
211        from parametric_surface import ParametricSurface
212        def g(x,y):
213            i=round( (x-xmin)/(xmax-xmin)*(num_points-1) )
214            j=round( (y-ymin)/(ymax-ymin)*(num_points-1) )
215            z=vals[int(j),int(i)]
216            return (x,y,z)
217
218        G = ParametricSurface(g, (list(numpy.r_[xmin:xmax:num_points*j]), list(numpy.r_[ymin:ymax:num_points*j])), texture=texture, **kwds)
219        G._set_extra_kwds(kwds)
220        return G
221
222    if interpolation_type =='spline':
223        from plot3d import plot3d
224        kx=kwds['kx'] if kwds.has_key('kx') else 3
225        ky=kwds['ky'] if kwds.has_key('ky') else 3
226        if kwds.has_key('degree'):
227            kx=kwds['degree']
228            ky=kwds['degree']
229
230        s=kwds['smoothing'] if kwds.has_key('smoothing') else len(x)-numpy.sqrt(2*len(x))
231        s=interpolate.bisplrep(x,y,z,[int(1)]*len(x),xmin,xmax,ymin,ymax,kx=kx,ky=ky,s=s)
232        f=lambda x,y: interpolate.bisplev(x,y,s)
233        return plot3d(f,(xmin,xmax),(ymin,ymax),texture=texture,plot_points=[num_points,num_points],**kwds)
Note: See TracBrowser for help on using the repository browser.