Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/plot/point.py
8815 views
1
"""
2
Points
3
4
TESTS::
5
6
sage: E = EllipticCurve('37a')
7
sage: P = E(0,0)
8
sage: def get_points(n): return sum([point(list(i*P)[:2], size=3) for i in range(-n,n) if i != 0 and (i*P)[0] < 3])
9
sage: sum([get_points(15*n).plot3d(z=n) for n in range(1,10)])
10
"""
11
12
#*****************************************************************************
13
# Copyright (C) 2006 Alex Clemesha <[email protected]>,
14
# William Stein <[email protected]>,
15
# 2008 Mike Hansen <[email protected]>,
16
#
17
# Distributed under the terms of the GNU General Public License (GPL)
18
#
19
# This code is distributed in the hope that it will be useful,
20
# but WITHOUT ANY WARRANTY; without even the implied warranty of
21
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22
# General Public License for more details.
23
#
24
# The full text of the GPL is available at:
25
#
26
# http://www.gnu.org/licenses/
27
#*****************************************************************************
28
from sage.misc.decorators import options, rename_keyword
29
from sage.plot.colors import to_mpl_color
30
from sage.plot.primitive import GraphicPrimitive_xydata
31
32
# TODO: create _allowed_options for 3D point classes to
33
# improve bad option handling in plot3d?
34
class Point(GraphicPrimitive_xydata):
35
"""
36
Primitive class for the point graphics type. See point?, point2d?
37
or point3d? for information about actually plotting points.
38
39
INPUT:
40
41
- xdata - list of x values for points in Point object
42
43
- ydata - list of y values for points in Point object
44
45
- options - dict of valid plot options to pass to constructor
46
47
EXAMPLES:
48
49
Note this should normally be used indirectly via ``point`` and friends::
50
51
sage: from sage.plot.point import Point
52
sage: P = Point([1,2],[2,3],{'alpha':.5})
53
sage: P
54
Point set defined by 2 point(s)
55
sage: P.options()['alpha']
56
0.500000000000000
57
sage: P.xdata
58
[1, 2]
59
60
TESTS:
61
62
We test creating a point::
63
64
sage: point((3,3))
65
"""
66
def __init__(self, xdata, ydata, options):
67
"""
68
Initializes base class Point.
69
70
EXAMPLES::
71
72
sage: P = point((3,4))
73
sage: P[0].xdata
74
[3.0]
75
sage: P[0].options()['alpha']
76
1
77
"""
78
self.xdata = xdata
79
self.ydata = ydata
80
GraphicPrimitive_xydata.__init__(self, options)
81
82
def _allowed_options(self):
83
"""
84
Return the allowed options for the Point class.
85
86
EXAMPLES::
87
88
sage: P = point((3,4))
89
sage: P[0]._allowed_options()['size']
90
'How big the point is (i.e., area in points^2=(1/72 inch)^2).'
91
"""
92
return {'alpha':'How transparent the point is.',
93
'legend_color':'The color of the legend text',
94
'legend_label':'The label for this item in the legend.',
95
'size': 'How big the point is (i.e., area in points^2=(1/72 inch)^2).',
96
'faceted': 'If True color the edge of the point.',
97
'rgbcolor':'The color as an RGB tuple.',
98
'hue':'The color given as a hue.',
99
'zorder':'The layer level in which to draw'}
100
101
def _plot3d_options(self, options=None):
102
"""
103
Translate 2D plot options into 3D plot options.
104
105
EXAMPLES::
106
107
sage: A=point((1,1),size=22)
108
sage: a=A[0];a
109
Point set defined by 1 point(s)
110
sage: b=a.plot3d()
111
sage: b.size
112
22
113
sage: b=a.plot3d(size=3)
114
sage: b.size
115
3
116
"""
117
if options == None:
118
options = dict(self.options())
119
options_3d = {}
120
if 'size' in options:
121
options_3d['size'] = options['size']
122
del options['size']
123
if 'faceted' in options:
124
if options['faceted']:
125
raise NotImplementedError, "No 3d faceted points."
126
del options['faceted']
127
options_3d.update(GraphicPrimitive_xydata._plot3d_options(self, options))
128
return options_3d
129
130
def plot3d(self, z=0, **kwds):
131
"""
132
Plots a two-dimensional point in 3-D, with default height zero.
133
134
INPUT:
135
136
137
- ``z`` - optional 3D height above `xy`-plane. May be a list
138
if self is a list of points.
139
140
EXAMPLES:
141
142
One point::
143
144
sage: A=point((1,1))
145
sage: a=A[0];a
146
Point set defined by 1 point(s)
147
sage: b=a.plot3d()
148
149
One point with a height::
150
151
sage: A=point((1,1))
152
sage: a=A[0];a
153
Point set defined by 1 point(s)
154
sage: b=a.plot3d(z=3)
155
sage: b.loc[2]
156
3.0
157
158
Multiple points::
159
160
sage: P=point([(0,0), (1,1)])
161
sage: p=P[0]; p
162
Point set defined by 2 point(s)
163
sage: q=p.plot3d(size=22)
164
165
Multiple points with different heights::
166
167
sage: P=point([(0,0), (1,1)])
168
sage: p=P[0]
169
sage: q=p.plot3d(z=[2,3])
170
sage: q.all[0].loc[2]
171
2.0
172
sage: q.all[1].loc[2]
173
3.0
174
175
Note that keywords passed must be valid point3d options::
176
177
sage: A=point((1,1),size=22)
178
sage: a=A[0];a
179
Point set defined by 1 point(s)
180
sage: b=a.plot3d()
181
sage: b.size
182
22
183
sage: b=a.plot3d(pointsize=23) # only 2D valid option
184
sage: b.size
185
22
186
sage: b=a.plot3d(size=23) # correct keyword
187
sage: b.size
188
23
189
190
TESTS:
191
192
Heights passed as a list should have same length as
193
number of points::
194
195
sage: P=point([(0,0), (1,1), (2,3)])
196
sage: p=P[0]
197
sage: q=p.plot3d(z=2)
198
sage: q.all[1].loc[2]
199
2.0
200
sage: q=p.plot3d(z=[2,-2])
201
Traceback (most recent call last):
202
...
203
ValueError: Incorrect number of heights given
204
"""
205
from sage.plot.plot3d.base import Graphics3dGroup
206
from sage.plot.plot3d.shapes2 import point3d
207
options = self._plot3d_options()
208
options.update(kwds)
209
zdata=[]
210
if type(z) is list:
211
zdata=z
212
else:
213
zdata=[z]*len(self.xdata)
214
if len(zdata)==len(self.xdata):
215
all = [point3d([(x, y, z) for x, y, z in zip(self.xdata, self.ydata, zdata)], **options)]
216
if len(all) == 1:
217
return all[0]
218
else:
219
return Graphics3dGroup(all)
220
else:
221
raise ValueError, 'Incorrect number of heights given'
222
223
def _repr_(self):
224
"""
225
String representation of Point primitive.
226
227
EXAMPLES::
228
229
sage: P=point([(0,0), (1,1)])
230
sage: p=P[0]; p
231
Point set defined by 2 point(s)
232
"""
233
return "Point set defined by %s point(s)"%len(self.xdata)
234
235
def __getitem__(self, i):
236
"""
237
Returns tuple of coordinates of point.
238
239
EXAMPLES::
240
241
sage: P=point([(0,0), (1,1), (2,3)])
242
sage: p=P[0]; p
243
Point set defined by 3 point(s)
244
sage: p[1]
245
(1.0, 1.0)
246
"""
247
return self.xdata[i], self.ydata[i]
248
249
def _render_on_subplot(self,subplot):
250
r"""
251
TESTS:
252
253
We check to make sure that \#2076 is fixed by verifying all
254
the points are red::
255
256
sage: point(((1,1), (2,2), (3,3)), rgbcolor=hue(1), size=30)
257
"""
258
options = self.options()
259
260
#Convert the color to a hex string so that the scatter
261
#method does not interpret it as a list of 3 floating
262
#point color specifications when there are
263
#three points. This is mentioned in the matplotlib 0.98
264
#documentation and fixes \#2076
265
from matplotlib.colors import rgb2hex
266
c = rgb2hex(to_mpl_color(options['rgbcolor']))
267
268
a = float(options['alpha'])
269
z = int(options.pop('zorder', 0))
270
s = int(options['size'])
271
faceted = options['faceted'] #faceted=True colors the edge of point
272
scatteroptions={}
273
if not faceted: scatteroptions['edgecolors'] = 'none'
274
subplot.scatter(self.xdata, self.ydata, s=s, c=c, alpha=a, zorder=z, label=options['legend_label'], **scatteroptions)
275
276
277
def point(points, **kwds):
278
"""
279
Returns either a 2-dimensional or 3-dimensional point or sum of points.
280
281
INPUT:
282
283
- ``points`` - either a single point (as a tuple), a list of
284
points, a single complex number, or a list of complex numbers.
285
286
For information regarding additional arguments, see either point2d?
287
or point3d?.
288
289
EXAMPLES::
290
291
sage: point((1,2))
292
293
::
294
295
sage: point((1,2,3))
296
297
::
298
299
sage: point([(0,0), (1,1)])
300
301
::
302
303
sage: point([(0,0,1), (1,1,1)])
304
305
Extra options will get passed on to show(), as long as they are valid::
306
307
sage: point([(cos(theta), sin(theta)) for theta in srange(0, 2*pi, pi/8)], frame=True)
308
sage: point([(cos(theta), sin(theta)) for theta in srange(0, 2*pi, pi/8)]).show(frame=True) # These are equivalent
309
"""
310
try:
311
return point2d(points, **kwds)
312
except (ValueError, TypeError):
313
from sage.plot.plot3d.shapes2 import point3d
314
return point3d(points, **kwds)
315
316
@rename_keyword(color='rgbcolor', pointsize='size')
317
@options(alpha=1, size=10, faceted=False, rgbcolor=(0,0,1),
318
legend_color=None, legend_label=None, aspect_ratio='automatic')
319
def point2d(points, **options):
320
r"""
321
A point of size ``size`` defined by point = `(x,y)`.
322
323
INPUT:
324
325
- ``points`` - either a single point (as a tuple), a list of
326
points, a single complex number, or a list of complex numbers.
327
328
Type ``point2d.options`` to see all options.
329
330
EXAMPLES:
331
332
A purple point from a single tuple or coordinates::
333
334
sage: point((0.5, 0.5), rgbcolor=hue(0.75))
335
336
Passing an empty list returns an empty plot::
337
338
sage: point([])
339
sage: import numpy; point(numpy.array([]))
340
341
If you need a 2D point to live in 3-space later,
342
this is possible::
343
344
sage: A=point((1,1))
345
sage: a=A[0];a
346
Point set defined by 1 point(s)
347
sage: b=a.plot3d(z=3)
348
349
This is also true with multiple points::
350
351
sage: P=point([(0,0), (1,1)])
352
sage: p=P[0]
353
sage: q=p.plot3d(z=[2,3])
354
355
Here are some random larger red points, given as a list of tuples::
356
357
sage: point(((0.5, 0.5), (1, 2), (0.5, 0.9), (-1, -1)), rgbcolor=hue(1), size=30)
358
359
And an example with a legend::
360
361
sage: point((0,0), rgbcolor='black', pointsize=40, legend_label='origin')
362
363
The legend can be colored::
364
365
sage: P = points([(0,0),(1,0)], pointsize=40, legend_label='origin', legend_color='red')
366
sage: P + plot(x^2,(x,0,1), legend_label='plot', legend_color='green')
367
368
Extra options will get passed on to show(), as long as they are valid::
369
370
sage: point([(cos(theta), sin(theta)) for theta in srange(0, 2*pi, pi/8)], frame=True)
371
sage: point([(cos(theta), sin(theta)) for theta in srange(0, 2*pi, pi/8)]).show(frame=True) # These are equivalent
372
373
For plotting data, we can use a logarithmic scale, as long as we are sure
374
not to include any nonpositive points in the logarithmic direction::
375
376
sage: point([(1,2),(2,4),(3,4),(4,8),(4.5,32)],scale='semilogy',base=2)
377
378
Since Sage Version 4.4 (ticket #8599), the size of a 2d point can be
379
given by the argument ``size`` instead of ``pointsize``. The argument
380
``pointsize`` is still supported::
381
382
sage: point((3,4), size=100)
383
384
::
385
386
sage: point((3,4), pointsize=100)
387
388
We can plot a single complex number::
389
390
sage: point(CC(1+I), pointsize=100)
391
392
We can also plot a list of complex numbers::
393
394
sage: point([CC(I), CC(I+1), CC(2+2*I)], pointsize=100)
395
396
"""
397
from sage.plot.plot import xydata_from_point_list
398
from sage.plot.all import Graphics
399
from sage.rings.all import CC, CDF
400
if points in CC or points in CDF:
401
pass
402
else:
403
try:
404
if not points:
405
return Graphics()
406
except ValueError: # numpy raises a ValueError if not empty
407
pass
408
xdata, ydata = xydata_from_point_list(points)
409
g = Graphics()
410
g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
411
g.add_primitive(Point(xdata, ydata, options))
412
if options['legend_label']:
413
g.legend(True)
414
g._legend_colors = [options['legend_color']]
415
return g
416
417
points = point
418
419