passagemath-plot 10.6.31rc3__cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-plot might be problematic. Click here for more details.
- passagemath_plot-10.6.31rc3.dist-info/METADATA +172 -0
- passagemath_plot-10.6.31rc3.dist-info/RECORD +81 -0
- passagemath_plot-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_plot-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_plot.libs/libgfortran-e1b7dfc8.so.5.0.0 +0 -0
- passagemath_plot.libs/libgsl-e3525837.so.28.0.0 +0 -0
- passagemath_plot.libs/libopenblasp-r0-4c5b64b1.3.29.so +0 -0
- sage/all__sagemath_plot.py +15 -0
- sage/ext_data/threejs/animation.css +195 -0
- sage/ext_data/threejs/animation.html +85 -0
- sage/ext_data/threejs/animation.js +273 -0
- sage/ext_data/threejs/fat_lines.js +48 -0
- sage/ext_data/threejs/threejs-version.txt +1 -0
- sage/ext_data/threejs/threejs_template.html +597 -0
- sage/interfaces/all__sagemath_plot.py +1 -0
- sage/interfaces/gnuplot.py +196 -0
- sage/interfaces/jmoldata.py +208 -0
- sage/interfaces/povray.py +56 -0
- sage/plot/all.py +42 -0
- sage/plot/animate.py +1796 -0
- sage/plot/arc.py +504 -0
- sage/plot/arrow.py +671 -0
- sage/plot/bar_chart.py +205 -0
- sage/plot/bezier_path.py +400 -0
- sage/plot/circle.py +435 -0
- sage/plot/colors.py +1606 -0
- sage/plot/complex_plot.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/plot/complex_plot.pyx +1446 -0
- sage/plot/contour_plot.py +1792 -0
- sage/plot/density_plot.py +318 -0
- sage/plot/disk.py +373 -0
- sage/plot/ellipse.py +375 -0
- sage/plot/graphics.py +3580 -0
- sage/plot/histogram.py +354 -0
- sage/plot/hyperbolic_arc.py +404 -0
- sage/plot/hyperbolic_polygon.py +416 -0
- sage/plot/hyperbolic_regular_polygon.py +296 -0
- sage/plot/line.py +626 -0
- sage/plot/matrix_plot.py +629 -0
- sage/plot/misc.py +509 -0
- sage/plot/multigraphics.py +1294 -0
- sage/plot/plot.py +4183 -0
- sage/plot/plot3d/all.py +23 -0
- sage/plot/plot3d/base.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/plot/plot3d/base.pxd +12 -0
- sage/plot/plot3d/base.pyx +3378 -0
- sage/plot/plot3d/implicit_plot3d.py +659 -0
- sage/plot/plot3d/implicit_surface.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/plot/plot3d/implicit_surface.pyx +1453 -0
- sage/plot/plot3d/index_face_set.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/plot/plot3d/index_face_set.pxd +32 -0
- sage/plot/plot3d/index_face_set.pyx +1873 -0
- sage/plot/plot3d/introduction.py +131 -0
- sage/plot/plot3d/list_plot3d.py +649 -0
- sage/plot/plot3d/parametric_plot3d.py +1130 -0
- sage/plot/plot3d/parametric_surface.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/plot/plot3d/parametric_surface.pxd +12 -0
- sage/plot/plot3d/parametric_surface.pyx +893 -0
- sage/plot/plot3d/platonic.py +601 -0
- sage/plot/plot3d/plot3d.py +1442 -0
- sage/plot/plot3d/plot_field3d.py +162 -0
- sage/plot/plot3d/point_c.pxi +148 -0
- sage/plot/plot3d/revolution_plot3d.py +309 -0
- sage/plot/plot3d/shapes.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/plot/plot3d/shapes.pxd +22 -0
- sage/plot/plot3d/shapes.pyx +1382 -0
- sage/plot/plot3d/shapes2.py +1512 -0
- sage/plot/plot3d/tachyon.py +1779 -0
- sage/plot/plot3d/texture.py +453 -0
- sage/plot/plot3d/transform.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/plot/plot3d/transform.pxd +21 -0
- sage/plot/plot3d/transform.pyx +268 -0
- sage/plot/plot3d/tri_plot.py +589 -0
- sage/plot/plot_field.py +362 -0
- sage/plot/point.py +624 -0
- sage/plot/polygon.py +562 -0
- sage/plot/primitive.py +249 -0
- sage/plot/scatter_plot.py +199 -0
- sage/plot/step.py +85 -0
- sage/plot/streamline_plot.py +328 -0
- sage/plot/text.py +432 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-plot
|
|
2
|
+
# sage.doctest: needs sage.symbolic
|
|
3
|
+
"""
|
|
4
|
+
Density plots
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
#*****************************************************************************
|
|
8
|
+
# Copyright (C) 2006 Alex Clemesha <clemesha@gmail.com>,
|
|
9
|
+
# William Stein <wstein@gmail.com>,
|
|
10
|
+
# 2008 Mike Hansen <mhansen@gmail.com>,
|
|
11
|
+
# Arnaud Bergeron <abergeron@gmail.com>
|
|
12
|
+
#
|
|
13
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
14
|
+
#
|
|
15
|
+
# This code is distributed in the hope that it will be useful,
|
|
16
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
18
|
+
# General Public License for more details.
|
|
19
|
+
#
|
|
20
|
+
# The full text of the GPL is available at:
|
|
21
|
+
#
|
|
22
|
+
# http://www.gnu.org/licenses/
|
|
23
|
+
#*****************************************************************************
|
|
24
|
+
from sage.plot.primitive import GraphicPrimitive
|
|
25
|
+
from sage.misc.decorators import options
|
|
26
|
+
from sage.plot.colors import get_cmap
|
|
27
|
+
from sage.arith.srange import xsrange
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class DensityPlot(GraphicPrimitive):
|
|
31
|
+
"""
|
|
32
|
+
Primitive class for the density plot graphics type. See
|
|
33
|
+
``density_plot?`` for help actually doing density plots.
|
|
34
|
+
|
|
35
|
+
INPUT:
|
|
36
|
+
|
|
37
|
+
- ``xy_data_array`` -- list of lists giving evaluated values of the
|
|
38
|
+
function on the grid
|
|
39
|
+
|
|
40
|
+
- ``xrange`` -- tuple of 2 floats indicating range for horizontal direction
|
|
41
|
+
|
|
42
|
+
- ``yrange`` -- tuple of 2 floats indicating range for vertical direction
|
|
43
|
+
|
|
44
|
+
- ``options`` -- dictionary of valid plot options to pass to constructor
|
|
45
|
+
|
|
46
|
+
EXAMPLES:
|
|
47
|
+
|
|
48
|
+
Note this should normally be used indirectly via ``density_plot``::
|
|
49
|
+
|
|
50
|
+
sage: from sage.plot.density_plot import DensityPlot
|
|
51
|
+
sage: D = DensityPlot([[1,3],[2,4]], (1,2), (2,3),options={})
|
|
52
|
+
sage: D
|
|
53
|
+
DensityPlot defined by a 2 x 2 data grid
|
|
54
|
+
sage: D.yrange
|
|
55
|
+
(2, 3)
|
|
56
|
+
sage: D.options()
|
|
57
|
+
{}
|
|
58
|
+
|
|
59
|
+
TESTS:
|
|
60
|
+
|
|
61
|
+
We test creating a density plot::
|
|
62
|
+
|
|
63
|
+
sage: x,y = var('x,y')
|
|
64
|
+
sage: density_plot(x^2 - y^3 + 10*sin(x*y), (x,-4,4), (y,-4,4), plot_points=121, cmap='hsv')
|
|
65
|
+
Graphics object consisting of 1 graphics primitive
|
|
66
|
+
"""
|
|
67
|
+
def __init__(self, xy_data_array, xrange, yrange, options):
|
|
68
|
+
"""
|
|
69
|
+
Initialize base class ``DensityPlot``.
|
|
70
|
+
|
|
71
|
+
EXAMPLES::
|
|
72
|
+
|
|
73
|
+
sage: x,y = var('x,y')
|
|
74
|
+
sage: D = density_plot(x^2 - y^3 + 10*sin(x*y), (x,-4,4), (y,-4,4), plot_points=121, cmap='hsv')
|
|
75
|
+
sage: D[0].xrange
|
|
76
|
+
(-4.0, 4.0)
|
|
77
|
+
sage: D[0].options()['plot_points']
|
|
78
|
+
121
|
|
79
|
+
"""
|
|
80
|
+
self.xrange = xrange
|
|
81
|
+
self.yrange = yrange
|
|
82
|
+
self.xy_data_array = xy_data_array
|
|
83
|
+
self.xy_array_row = len(xy_data_array)
|
|
84
|
+
self.xy_array_col = len(xy_data_array[0])
|
|
85
|
+
GraphicPrimitive.__init__(self, options)
|
|
86
|
+
|
|
87
|
+
def get_minmax_data(self):
|
|
88
|
+
"""
|
|
89
|
+
Return a dictionary with the bounding box data.
|
|
90
|
+
|
|
91
|
+
EXAMPLES::
|
|
92
|
+
|
|
93
|
+
sage: x,y = var('x,y')
|
|
94
|
+
sage: f(x, y) = x^2 + y^2
|
|
95
|
+
sage: d = density_plot(f, (3,6), (3,6))[0].get_minmax_data()
|
|
96
|
+
sage: d['xmin']
|
|
97
|
+
3.0
|
|
98
|
+
sage: d['ymin']
|
|
99
|
+
3.0
|
|
100
|
+
"""
|
|
101
|
+
from sage.plot.plot import minmax_data
|
|
102
|
+
return minmax_data(self.xrange, self.yrange, dict=True)
|
|
103
|
+
|
|
104
|
+
def _allowed_options(self):
|
|
105
|
+
"""
|
|
106
|
+
Return the allowed options for the DensityPlot class.
|
|
107
|
+
|
|
108
|
+
TESTS::
|
|
109
|
+
|
|
110
|
+
sage: isinstance(density_plot(x, (-2,3), (1,10))[0]._allowed_options(), dict)
|
|
111
|
+
True
|
|
112
|
+
"""
|
|
113
|
+
return {'plot_points': 'How many points to use for plotting precision',
|
|
114
|
+
'cmap': """the name of a predefined colormap,
|
|
115
|
+
a list of colors or an instance of a
|
|
116
|
+
matplotlib Colormap. Type: import matplotlib.cm; matplotlib.cm.datad.keys()
|
|
117
|
+
for available colormap names.""",
|
|
118
|
+
'interpolation': 'What interpolation method to use'}
|
|
119
|
+
|
|
120
|
+
def _repr_(self):
|
|
121
|
+
"""
|
|
122
|
+
String representation of DensityrPlot primitive.
|
|
123
|
+
|
|
124
|
+
EXAMPLES::
|
|
125
|
+
|
|
126
|
+
sage: x,y = var('x,y')
|
|
127
|
+
sage: D = density_plot(x^2 - y^2, (x,-2,2), (y,-2,2))
|
|
128
|
+
sage: d = D[0]; d
|
|
129
|
+
DensityPlot defined by a 25 x 25 data grid
|
|
130
|
+
"""
|
|
131
|
+
return "DensityPlot defined by a {} x {} data grid".format(self.xy_array_row, self.xy_array_col)
|
|
132
|
+
|
|
133
|
+
def _render_on_subplot(self, subplot):
|
|
134
|
+
"""
|
|
135
|
+
TESTS:
|
|
136
|
+
|
|
137
|
+
A somewhat random plot, but fun to look at::
|
|
138
|
+
|
|
139
|
+
sage: x,y = var('x,y')
|
|
140
|
+
sage: density_plot(x^2 - y^3 + 10*sin(x*y), (x,-4,4), (y,-4,4), plot_points=121, cmap='hsv')
|
|
141
|
+
Graphics object consisting of 1 graphics primitive
|
|
142
|
+
"""
|
|
143
|
+
options = self.options()
|
|
144
|
+
cmap = get_cmap(options['cmap'])
|
|
145
|
+
|
|
146
|
+
x0, x1 = float(self.xrange[0]), float(self.xrange[1])
|
|
147
|
+
y0, y1 = float(self.yrange[0]), float(self.yrange[1])
|
|
148
|
+
|
|
149
|
+
subplot.imshow(self.xy_data_array, origin='lower',
|
|
150
|
+
cmap=cmap, extent=(x0,x1,y0,y1),
|
|
151
|
+
interpolation=options['interpolation'])
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@options(plot_points=25, cmap='gray', interpolation='catrom')
|
|
155
|
+
def density_plot(f, xrange, yrange, **options):
|
|
156
|
+
r"""
|
|
157
|
+
``density_plot`` takes a function of two variables, `f(x,y)`
|
|
158
|
+
and plots the height of the function over the specified
|
|
159
|
+
``xrange`` and ``yrange`` as demonstrated below.
|
|
160
|
+
|
|
161
|
+
``density_plot(f, (xmin,xmax), (ymin,ymax), ...)``
|
|
162
|
+
|
|
163
|
+
INPUT:
|
|
164
|
+
|
|
165
|
+
- ``f`` -- a function of two variables
|
|
166
|
+
|
|
167
|
+
- ``(xmin, xmax)`` -- 2-tuple, the range of ``x`` values OR 3-tuple
|
|
168
|
+
``(x,xmin,xmax)``
|
|
169
|
+
|
|
170
|
+
- ``(ymin, ymax)`` -- 2-tuple, the range of ``y`` values OR 3-tuple
|
|
171
|
+
``(y,ymin,ymax)``
|
|
172
|
+
|
|
173
|
+
The following inputs must all be passed in as named parameters:
|
|
174
|
+
|
|
175
|
+
- ``plot_points`` -- integer (default: 25); number of points to plot
|
|
176
|
+
in each direction of the grid
|
|
177
|
+
|
|
178
|
+
- ``cmap`` -- a colormap (default: ``'gray'``), the name of
|
|
179
|
+
a predefined colormap, a list of colors or an instance of a matplotlib
|
|
180
|
+
Colormap. Type: ``import matplotlib.cm; matplotlib.cm.datad.keys()``
|
|
181
|
+
for available colormap names.
|
|
182
|
+
|
|
183
|
+
- ``interpolation`` -- string (default: ``'catrom'``); the interpolation
|
|
184
|
+
method to use: ``'bilinear'``, ``'bicubic'``, ``'spline16'``,
|
|
185
|
+
``'spline36'``, ``'quadric'``, ``'gaussian'``, ``'sinc'``,
|
|
186
|
+
``'bessel'``, ``'mitchell'``, ``'lanczos'``, ``'catrom'``,
|
|
187
|
+
``'hermite'``, ``'hanning'``, ``'hamming'``, ``'kaiser'``
|
|
188
|
+
|
|
189
|
+
EXAMPLES:
|
|
190
|
+
|
|
191
|
+
Here we plot a simple function of two variables. Note that
|
|
192
|
+
since the input function is an expression, we need to explicitly
|
|
193
|
+
declare the variables in 3-tuples for the range::
|
|
194
|
+
|
|
195
|
+
sage: x,y = var('x,y')
|
|
196
|
+
sage: density_plot(sin(x) * sin(y), (x,-2,2), (y,-2,2))
|
|
197
|
+
Graphics object consisting of 1 graphics primitive
|
|
198
|
+
|
|
199
|
+
.. PLOT::
|
|
200
|
+
|
|
201
|
+
x,y = var('x,y')
|
|
202
|
+
g = density_plot(sin(x) * sin(y), (x,-2,2), (y,-2,2))
|
|
203
|
+
sphinx_plot(g)
|
|
204
|
+
|
|
205
|
+
Here we change the ranges and add some options; note that here
|
|
206
|
+
``f`` is callable (has variables declared), so we can use 2-tuple ranges::
|
|
207
|
+
|
|
208
|
+
sage: x,y = var('x,y')
|
|
209
|
+
sage: f(x,y) = x^2 * cos(x*y)
|
|
210
|
+
sage: density_plot(f, (x,-10,5), (y,-5,5), interpolation='sinc', plot_points=100)
|
|
211
|
+
Graphics object consisting of 1 graphics primitive
|
|
212
|
+
|
|
213
|
+
.. PLOT::
|
|
214
|
+
|
|
215
|
+
x,y = var('x,y')
|
|
216
|
+
def f(x, y): return x**2 * cos(x*y)
|
|
217
|
+
g = density_plot(f, (x,-10,5), (y,-5,5), interpolation='sinc', plot_points=100)
|
|
218
|
+
sphinx_plot(g)
|
|
219
|
+
|
|
220
|
+
An even more complicated plot::
|
|
221
|
+
|
|
222
|
+
sage: x,y = var('x,y')
|
|
223
|
+
sage: density_plot(sin(x^2+y^2) * cos(x) * sin(y), (x,-4,4), (y,-4,4), cmap='jet', plot_points=100)
|
|
224
|
+
Graphics object consisting of 1 graphics primitive
|
|
225
|
+
|
|
226
|
+
.. PLOT::
|
|
227
|
+
|
|
228
|
+
x,y = var('x,y')
|
|
229
|
+
g = density_plot(sin(x**2 + y**2)*cos(x)*sin(y), (x,-4,4), (y,-4,4), cmap='jet', plot_points=100)
|
|
230
|
+
sphinx_plot(g)
|
|
231
|
+
|
|
232
|
+
This should show a "spotlight" right on the origin::
|
|
233
|
+
|
|
234
|
+
sage: x,y = var('x,y')
|
|
235
|
+
sage: density_plot(1/(x^10 + y^10), (x,-10,10), (y,-10,10))
|
|
236
|
+
Graphics object consisting of 1 graphics primitive
|
|
237
|
+
|
|
238
|
+
.. PLOT::
|
|
239
|
+
|
|
240
|
+
x,y = var('x,y')
|
|
241
|
+
g = density_plot(1/(x**10 + y**10), (x,-10,10), (y,-10,10))
|
|
242
|
+
sphinx_plot(g)
|
|
243
|
+
|
|
244
|
+
Some elliptic curves, but with symbolic endpoints. In the first
|
|
245
|
+
example, the plot is rotated 90 degrees because we switch the
|
|
246
|
+
variables `x`, `y`::
|
|
247
|
+
|
|
248
|
+
sage: density_plot(y^2 + 1 - x^3 - x, (y,-pi,pi), (x,-pi,pi))
|
|
249
|
+
Graphics object consisting of 1 graphics primitive
|
|
250
|
+
|
|
251
|
+
.. PLOT::
|
|
252
|
+
|
|
253
|
+
x,y = var('x,y')
|
|
254
|
+
g = density_plot(y**2 + 1 - x**3 - x, (y,-pi,pi), (x,-pi,pi))
|
|
255
|
+
sphinx_plot(g)
|
|
256
|
+
|
|
257
|
+
::
|
|
258
|
+
|
|
259
|
+
sage: density_plot(y^2 + 1 - x^3 - x, (x,-pi,pi), (y,-pi,pi))
|
|
260
|
+
Graphics object consisting of 1 graphics primitive
|
|
261
|
+
|
|
262
|
+
.. PLOT::
|
|
263
|
+
|
|
264
|
+
x,y = var('x,y')
|
|
265
|
+
g = density_plot(y**2 + 1 - x**3 - x, (x,-pi,pi), (y,-pi,pi))
|
|
266
|
+
sphinx_plot(g)
|
|
267
|
+
|
|
268
|
+
Extra options will get passed on to show(), as long as they are valid::
|
|
269
|
+
|
|
270
|
+
sage: density_plot(log(x) + log(y), (x,1,10), (y,1,10), aspect_ratio=1)
|
|
271
|
+
Graphics object consisting of 1 graphics primitive
|
|
272
|
+
|
|
273
|
+
.. PLOT::
|
|
274
|
+
|
|
275
|
+
x,y = var('x,y')
|
|
276
|
+
g = density_plot(log(x) + log(y), (x,1,10), (y,1,10), aspect_ratio=1)
|
|
277
|
+
sphinx_plot(g)
|
|
278
|
+
|
|
279
|
+
::
|
|
280
|
+
|
|
281
|
+
sage: density_plot(log(x) + log(y), (x,1,10), (y,1,10)).show(aspect_ratio=1) # These are equivalent
|
|
282
|
+
|
|
283
|
+
TESTS:
|
|
284
|
+
|
|
285
|
+
Check that :issue:`15315` is fixed, i.e., density_plot respects the
|
|
286
|
+
``aspect_ratio`` parameter. Without the fix, it looks like a thin line
|
|
287
|
+
of width a few mm. With the fix it should look like a nice fat layered
|
|
288
|
+
image::
|
|
289
|
+
|
|
290
|
+
sage: density_plot((x*y)^(1/2), (x,0,3), (y,0,500), aspect_ratio=.01)
|
|
291
|
+
Graphics object consisting of 1 graphics primitive
|
|
292
|
+
|
|
293
|
+
Default ``aspect_ratio`` is ``'automatic'``, and that should work too::
|
|
294
|
+
|
|
295
|
+
sage: density_plot((x*y)^(1/2), (x,0,3), (y,0,500))
|
|
296
|
+
Graphics object consisting of 1 graphics primitive
|
|
297
|
+
|
|
298
|
+
Check that :issue:`17684` is fixed, i.e., symbolic values can be plotted::
|
|
299
|
+
|
|
300
|
+
sage: def f(x, y):
|
|
301
|
+
....: return SR(x)
|
|
302
|
+
sage: density_plot(f, (0,1), (0,1))
|
|
303
|
+
Graphics object consisting of 1 graphics primitive
|
|
304
|
+
"""
|
|
305
|
+
from sage.plot.all import Graphics
|
|
306
|
+
from sage.plot.misc import setup_for_eval_on_grid
|
|
307
|
+
from sage.rings.real_double import RDF
|
|
308
|
+
g, ranges = setup_for_eval_on_grid([f], [xrange, yrange], options['plot_points'])
|
|
309
|
+
g = g[0]
|
|
310
|
+
xrange, yrange = (r[:2] for r in ranges)
|
|
311
|
+
|
|
312
|
+
xy_data_array = [[RDF(g(x,y)) for x in xsrange(*ranges[0], include_endpoint=True)]
|
|
313
|
+
for y in xsrange(*ranges[1], include_endpoint=True)]
|
|
314
|
+
|
|
315
|
+
g = Graphics()
|
|
316
|
+
g._set_extra_kwds(Graphics._extract_kwds_for_show(options, ignore=['xmin','xmax']))
|
|
317
|
+
g.add_primitive(DensityPlot(xy_data_array, xrange, yrange, options))
|
|
318
|
+
return g
|
sage/plot/disk.py
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-plot
|
|
2
|
+
"""
|
|
3
|
+
Disks
|
|
4
|
+
"""
|
|
5
|
+
# *****************************************************************************
|
|
6
|
+
# Copyright (C) 2006 Alex Clemesha <clemesha@gmail.com>,
|
|
7
|
+
# William Stein <wstein@gmail.com>,
|
|
8
|
+
# 2008 Mike Hansen <mhansen@gmail.com>,
|
|
9
|
+
# 2021 Javier Honrubia <jhonrubia6@alumno.uned.es>
|
|
10
|
+
#
|
|
11
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
12
|
+
#
|
|
13
|
+
# This code is distributed in the hope that it will be useful,
|
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
16
|
+
# General Public License for more details.
|
|
17
|
+
#
|
|
18
|
+
# The full text of the GPL is available at:
|
|
19
|
+
#
|
|
20
|
+
# http://www.gnu.org/licenses/
|
|
21
|
+
# *****************************************************************************
|
|
22
|
+
|
|
23
|
+
from sage.plot.primitive import GraphicPrimitive
|
|
24
|
+
from sage.misc.decorators import options, rename_keyword
|
|
25
|
+
from sage.plot.colors import to_mpl_color
|
|
26
|
+
from math import sin, cos, pi
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Disk(GraphicPrimitive):
|
|
30
|
+
"""
|
|
31
|
+
Primitive class for the ``Disk`` graphics type. See ``disk?`` for
|
|
32
|
+
information about actually plotting a disk (the Sage term for a sector
|
|
33
|
+
or wedge of a circle).
|
|
34
|
+
|
|
35
|
+
INPUT:
|
|
36
|
+
|
|
37
|
+
- ``point`` -- coordinates of center of disk
|
|
38
|
+
|
|
39
|
+
- ``r`` -- radius of disk
|
|
40
|
+
|
|
41
|
+
- ``angle`` -- beginning and ending angles of disk (i.e.
|
|
42
|
+
angle extent of sector/wedge)
|
|
43
|
+
|
|
44
|
+
- ``options`` -- dictionary of valid plot options to pass to constructor
|
|
45
|
+
|
|
46
|
+
EXAMPLES:
|
|
47
|
+
|
|
48
|
+
Note this should normally be used indirectly via ``disk``::
|
|
49
|
+
|
|
50
|
+
sage: from math import pi
|
|
51
|
+
sage: from sage.plot.disk import Disk
|
|
52
|
+
sage: D = Disk((1,2), 2, (pi/2,pi), {'zorder':3})
|
|
53
|
+
sage: D
|
|
54
|
+
Disk defined by (1.0,2.0) with r=2.0
|
|
55
|
+
spanning (1.5707963267..., 3.1415926535...) radians
|
|
56
|
+
sage: D.options()['zorder']
|
|
57
|
+
3
|
|
58
|
+
sage: D.x
|
|
59
|
+
1.0
|
|
60
|
+
|
|
61
|
+
TESTS:
|
|
62
|
+
|
|
63
|
+
We test creating a disk::
|
|
64
|
+
|
|
65
|
+
sage: disk((2,3), 2, (0,pi/2))
|
|
66
|
+
Graphics object consisting of 1 graphics primitive
|
|
67
|
+
"""
|
|
68
|
+
def __init__(self, point, r, angle, options):
|
|
69
|
+
"""
|
|
70
|
+
Initialize base class ``Disk``.
|
|
71
|
+
|
|
72
|
+
EXAMPLES::
|
|
73
|
+
|
|
74
|
+
sage: from math import pi
|
|
75
|
+
sage: D = disk((2,3), 1, (pi/2, pi), fill=False, color='red', thickness=1, alpha=.5)
|
|
76
|
+
sage: D[0].x
|
|
77
|
+
2.0
|
|
78
|
+
sage: D[0].r
|
|
79
|
+
1.0
|
|
80
|
+
sage: D[0].rad1
|
|
81
|
+
1.5707963267948966
|
|
82
|
+
sage: D[0].options()['rgbcolor']
|
|
83
|
+
'red'
|
|
84
|
+
sage: D[0].options()['alpha']
|
|
85
|
+
0.500000000000000
|
|
86
|
+
sage: print(loads(dumps(D)))
|
|
87
|
+
Graphics object consisting of 1 graphics primitive
|
|
88
|
+
"""
|
|
89
|
+
self.x = float(point[0])
|
|
90
|
+
self.y = float(point[1])
|
|
91
|
+
self.r = float(r)
|
|
92
|
+
self.rad1 = float(angle[0])
|
|
93
|
+
self.rad2 = float(angle[1])
|
|
94
|
+
GraphicPrimitive.__init__(self, options)
|
|
95
|
+
|
|
96
|
+
def get_minmax_data(self):
|
|
97
|
+
"""
|
|
98
|
+
Return a dictionary with the bounding box data.
|
|
99
|
+
|
|
100
|
+
EXAMPLES::
|
|
101
|
+
|
|
102
|
+
sage: from math import pi
|
|
103
|
+
sage: D = disk((5,4), 1, (pi/2, pi))
|
|
104
|
+
sage: d = D.get_minmax_data()
|
|
105
|
+
sage: d['xmin']
|
|
106
|
+
4.0
|
|
107
|
+
sage: d['ymin']
|
|
108
|
+
3.0
|
|
109
|
+
sage: d['xmax']
|
|
110
|
+
6.0
|
|
111
|
+
sage: d['ymax']
|
|
112
|
+
5.0
|
|
113
|
+
"""
|
|
114
|
+
from sage.plot.plot import minmax_data
|
|
115
|
+
return minmax_data([self.x - self.r, self.x + self.r],
|
|
116
|
+
[self.y - self.r, self.y + self.r],
|
|
117
|
+
dict=True)
|
|
118
|
+
|
|
119
|
+
def _allowed_options(self):
|
|
120
|
+
"""
|
|
121
|
+
Return the allowed options for the ``Disk`` class.
|
|
122
|
+
|
|
123
|
+
EXAMPLES::
|
|
124
|
+
|
|
125
|
+
sage: from math import pi
|
|
126
|
+
sage: p = disk((3, 3), 1, (0, pi/2))
|
|
127
|
+
sage: p[0]._allowed_options()['alpha']
|
|
128
|
+
'How transparent the figure is.'
|
|
129
|
+
sage: p[0]._allowed_options()['zorder']
|
|
130
|
+
'The layer level in which to draw'
|
|
131
|
+
"""
|
|
132
|
+
return {'alpha': 'How transparent the figure is.',
|
|
133
|
+
'fill': 'Whether or not to fill the disk.',
|
|
134
|
+
'legend_label': 'The label for this item in the legend.',
|
|
135
|
+
'legend_color': 'The color of the legend text.',
|
|
136
|
+
'thickness': 'How thick the border of the disk is.',
|
|
137
|
+
'rgbcolor': 'The color as an RGB tuple.',
|
|
138
|
+
'hue': 'The color given as a hue.',
|
|
139
|
+
'zorder': 'The layer level in which to draw'}
|
|
140
|
+
|
|
141
|
+
def _repr_(self):
|
|
142
|
+
"""
|
|
143
|
+
String representation of ``Disk`` primitive.
|
|
144
|
+
|
|
145
|
+
EXAMPLES::
|
|
146
|
+
|
|
147
|
+
sage: from math import pi
|
|
148
|
+
sage: P = disk((3, 3), 1, (0, pi/2))
|
|
149
|
+
sage: p = P[0]; p
|
|
150
|
+
Disk defined by (3.0,3.0) with r=1.0 spanning (0.0, 1.5707963267...) radians
|
|
151
|
+
"""
|
|
152
|
+
return "Disk defined by ({},{}) with r={} spanning ({}, {}) radians".format(self.x, self.y, self.r, self.rad1, self.rad2)
|
|
153
|
+
|
|
154
|
+
def _render_on_subplot(self, subplot):
|
|
155
|
+
"""
|
|
156
|
+
TESTS::
|
|
157
|
+
|
|
158
|
+
sage: from math import pi
|
|
159
|
+
sage: D = disk((2,-1), 2, (0, pi), color='black', thickness=3, fill=False); D
|
|
160
|
+
Graphics object consisting of 1 graphics primitive
|
|
161
|
+
|
|
162
|
+
Save alpha information in pdf (see :issue:`13732`)::
|
|
163
|
+
|
|
164
|
+
sage: f = tmp_filename(ext='.pdf')
|
|
165
|
+
sage: p = disk((0,0), 5, (0, pi/4), alpha=0.5)
|
|
166
|
+
sage: p.save(f)
|
|
167
|
+
"""
|
|
168
|
+
import matplotlib.patches as patches
|
|
169
|
+
options = self.options()
|
|
170
|
+
deg1 = self.rad1*(180./pi) # convert radians to degrees
|
|
171
|
+
deg2 = self.rad2*(180./pi)
|
|
172
|
+
z = int(options.pop('zorder', 0))
|
|
173
|
+
p = patches.Wedge((float(self.x), float(self.y)), float(self.r), float(deg1),
|
|
174
|
+
float(deg2), zorder=z)
|
|
175
|
+
a = float(options['alpha'])
|
|
176
|
+
p.set_alpha(a)
|
|
177
|
+
p.set_linewidth(float(options['thickness']))
|
|
178
|
+
p.set_fill(options['fill'])
|
|
179
|
+
c = to_mpl_color(options['rgbcolor'])
|
|
180
|
+
p.set_edgecolor(c)
|
|
181
|
+
p.set_facecolor(c)
|
|
182
|
+
p.set_label(options['legend_label'])
|
|
183
|
+
subplot.add_patch(p)
|
|
184
|
+
|
|
185
|
+
def plot3d(self, z=0, **kwds):
|
|
186
|
+
"""
|
|
187
|
+
Plots a 2D disk (actually a 52-gon) in 3D,
|
|
188
|
+
with default height zero.
|
|
189
|
+
|
|
190
|
+
INPUT:
|
|
191
|
+
|
|
192
|
+
- ``z`` -- (optional) 3D height above `xy`-plane
|
|
193
|
+
|
|
194
|
+
AUTHORS:
|
|
195
|
+
|
|
196
|
+
- Karl-Dieter Crisman (05-09)
|
|
197
|
+
|
|
198
|
+
EXAMPLES::
|
|
199
|
+
|
|
200
|
+
sage: from math import pi
|
|
201
|
+
sage: disk((0,0), 1, (0, pi/2)).plot3d()
|
|
202
|
+
Graphics3d Object
|
|
203
|
+
sage: disk((0,0), 1, (0, pi/2)).plot3d(z=2)
|
|
204
|
+
Graphics3d Object
|
|
205
|
+
sage: disk((0,0), 1, (pi/2, 0), fill=False).plot3d(3)
|
|
206
|
+
Graphics3d Object
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
These examples show that the appropriate options are passed::
|
|
210
|
+
|
|
211
|
+
sage: D = disk((2,3), 1, (pi/4,pi/3), hue=.8, alpha=.3, fill=True)
|
|
212
|
+
sage: d = D[0]
|
|
213
|
+
sage: d.plot3d(z=2).texture.opacity
|
|
214
|
+
0.3
|
|
215
|
+
|
|
216
|
+
::
|
|
217
|
+
|
|
218
|
+
sage: D = disk((2,3), 1, (pi/4,pi/3), hue=.8, alpha=.3, fill=False)
|
|
219
|
+
sage: d = D[0]
|
|
220
|
+
sage: dd = d.plot3d(z=2)
|
|
221
|
+
sage: dd.jmol_repr(dd.testing_render_params())[0][-1]
|
|
222
|
+
'color $line_4 translucent 0.7 [204,0,255]'
|
|
223
|
+
"""
|
|
224
|
+
options = dict(self.options())
|
|
225
|
+
fill = options['fill']
|
|
226
|
+
del options['fill']
|
|
227
|
+
if 'zorder' in options:
|
|
228
|
+
del options['zorder']
|
|
229
|
+
n = 50
|
|
230
|
+
x, y, r, rad1, rad2 = self.x, self.y, self.r, self.rad1, self.rad2
|
|
231
|
+
dt = float((rad2-rad1)/n)
|
|
232
|
+
xdata = [x]
|
|
233
|
+
ydata = [y]
|
|
234
|
+
xdata.extend([x+r*cos(t*dt+rad1) for t in range(n+1)])
|
|
235
|
+
ydata.extend([y+r*sin(t*dt+rad1) for t in range(n+1)])
|
|
236
|
+
xdata.append(x)
|
|
237
|
+
ydata.append(y)
|
|
238
|
+
if fill:
|
|
239
|
+
from .polygon import Polygon
|
|
240
|
+
return Polygon(xdata, ydata, options).plot3d(z)
|
|
241
|
+
else:
|
|
242
|
+
from .line import Line
|
|
243
|
+
return Line(xdata, ydata, options).plot3d().translate((0, 0, z))
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@rename_keyword(color='rgbcolor')
|
|
247
|
+
@options(alpha=1, fill=True, rgbcolor=(0, 0, 1), thickness=0, legend_label=None,
|
|
248
|
+
legend_color=None, aspect_ratio=1.0)
|
|
249
|
+
def disk(point, radius, angle, **options):
|
|
250
|
+
r"""
|
|
251
|
+
A disk (that is, a sector or wedge of a circle) with center
|
|
252
|
+
at a point = `(x,y)` (or `(x,y,z)` and parallel to the
|
|
253
|
+
`xy`-plane) with radius = `r` spanning (in radians)
|
|
254
|
+
angle=`(rad1, rad2)`.
|
|
255
|
+
|
|
256
|
+
Type ``disk.options`` to see all options.
|
|
257
|
+
|
|
258
|
+
EXAMPLES:
|
|
259
|
+
|
|
260
|
+
Make some dangerous disks::
|
|
261
|
+
|
|
262
|
+
sage: from math import pi
|
|
263
|
+
sage: bl = disk((0.0,0.0), 1, (pi, 3*pi/2), color='yellow')
|
|
264
|
+
sage: tr = disk((0.0,0.0), 1, (0, pi/2), color='yellow')
|
|
265
|
+
sage: tl = disk((0.0,0.0), 1, (pi/2, pi), color='black')
|
|
266
|
+
sage: br = disk((0.0,0.0), 1, (3*pi/2, 2*pi), color='black')
|
|
267
|
+
sage: P = tl + tr + bl + br
|
|
268
|
+
sage: P.show(xmin=-2, xmax=2, ymin=-2, ymax=2)
|
|
269
|
+
|
|
270
|
+
.. PLOT::
|
|
271
|
+
|
|
272
|
+
from sage.plot.disk import Disk
|
|
273
|
+
bl = disk((0.0,0.0), 1, (pi, 3*pi/2), color='yellow')
|
|
274
|
+
tr = disk((0.0,0.0), 1, (0, pi/2), color='yellow')
|
|
275
|
+
tl = disk((0.0,0.0), 1, (pi/2, pi), color='black')
|
|
276
|
+
br = disk((0.0,0.0), 1, (3*pi/2, 2*pi), color='black')
|
|
277
|
+
P = tl+tr+bl+br
|
|
278
|
+
sphinx_plot(P)
|
|
279
|
+
|
|
280
|
+
The default aspect ratio is 1.0::
|
|
281
|
+
|
|
282
|
+
sage: disk((0.0,0.0), 1, (pi, 3*pi/2)).aspect_ratio()
|
|
283
|
+
1.0
|
|
284
|
+
|
|
285
|
+
Another example of a disk::
|
|
286
|
+
|
|
287
|
+
sage: bl = disk((0.0,0.0), 1, (pi, 3*pi/2), rgbcolor=(1,1,0))
|
|
288
|
+
sage: bl.show(figsize=[5,5])
|
|
289
|
+
|
|
290
|
+
.. PLOT::
|
|
291
|
+
|
|
292
|
+
from sage.plot.disk import Disk
|
|
293
|
+
bl = disk((0.0,0.0), 1, (pi, 3*pi/2), rgbcolor=(1,1,0))
|
|
294
|
+
sphinx_plot(bl)
|
|
295
|
+
|
|
296
|
+
Note that since ``thickness`` defaults to zero, it is best to change
|
|
297
|
+
that option when using ``fill=False``::
|
|
298
|
+
|
|
299
|
+
sage: disk((2,3), 1, (pi/4,pi/3), hue=.8, alpha=.3, fill=False, thickness=2)
|
|
300
|
+
Graphics object consisting of 1 graphics primitive
|
|
301
|
+
|
|
302
|
+
.. PLOT::
|
|
303
|
+
|
|
304
|
+
from sage.plot.disk import Disk
|
|
305
|
+
D = disk((2,3), 1, (pi/4,pi/3), hue=.8, alpha=.3, fill=False, thickness=2)
|
|
306
|
+
sphinx_plot(D)
|
|
307
|
+
|
|
308
|
+
The previous two examples also illustrate using ``hue`` and ``rgbcolor``
|
|
309
|
+
as ways of specifying the color of the graphic.
|
|
310
|
+
|
|
311
|
+
We can also use this command to plot three-dimensional disks parallel
|
|
312
|
+
to the `xy`-plane::
|
|
313
|
+
|
|
314
|
+
sage: d = disk((1,1,3), 1, (pi,3*pi/2), rgbcolor=(1,0,0))
|
|
315
|
+
sage: d
|
|
316
|
+
Graphics3d Object
|
|
317
|
+
sage: type(d)
|
|
318
|
+
<... 'sage.plot.plot3d.index_face_set.IndexFaceSet'>
|
|
319
|
+
|
|
320
|
+
.. PLOT::
|
|
321
|
+
|
|
322
|
+
from sage.plot.disk import Disk
|
|
323
|
+
d = disk((1,1,3), 1, (pi,3*pi/2), rgbcolor=(1,0,0))
|
|
324
|
+
sphinx_plot(d)
|
|
325
|
+
|
|
326
|
+
Extra options will get passed on to ``show()``, as long as they are valid::
|
|
327
|
+
|
|
328
|
+
sage: disk((0, 0), 5, (0, pi/2), rgbcolor=(1, 0, 1),
|
|
329
|
+
....: xmin=0, xmax=5, ymin=0, ymax=5, figsize=(2,2))
|
|
330
|
+
Graphics object consisting of 1 graphics primitive
|
|
331
|
+
sage: disk((0, 0), 5, (0, pi/2), rgbcolor=(1, 0, 1)).show( # These are equivalent
|
|
332
|
+
....: xmin=0, xmax=5, ymin=0, ymax=5, figsize=(2,2))
|
|
333
|
+
|
|
334
|
+
TESTS:
|
|
335
|
+
|
|
336
|
+
Testing that legend labels work right::
|
|
337
|
+
|
|
338
|
+
sage: disk((2,4), 3, (pi/8, pi/4), hue=1, legend_label='disk', legend_color='blue')
|
|
339
|
+
Graphics object consisting of 1 graphics primitive
|
|
340
|
+
|
|
341
|
+
We cannot currently plot disks in more than three dimensions::
|
|
342
|
+
|
|
343
|
+
sage: d = disk((1,1,1,1), 1, (0,pi))
|
|
344
|
+
Traceback (most recent call last):
|
|
345
|
+
...
|
|
346
|
+
ValueError: the center point of a plotted disk should have two or three coordinates
|
|
347
|
+
|
|
348
|
+
Verify that :issue:`36153` is fixed::
|
|
349
|
+
|
|
350
|
+
sage: D = disk((0, 0), 5, (0, pi/2), legend_label='test')
|
|
351
|
+
"""
|
|
352
|
+
from sage.plot.all import Graphics
|
|
353
|
+
g = Graphics()
|
|
354
|
+
|
|
355
|
+
# Reset aspect_ratio to 'automatic' in case scale is 'semilog[xy]'.
|
|
356
|
+
# Otherwise matplotlib complains.
|
|
357
|
+
scale = options.get('scale', None)
|
|
358
|
+
if isinstance(scale, (list, tuple)):
|
|
359
|
+
scale = scale[0]
|
|
360
|
+
if scale == 'semilogy' or scale == 'semilogx':
|
|
361
|
+
options['aspect_ratio'] = 'automatic'
|
|
362
|
+
|
|
363
|
+
g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
|
|
364
|
+
g.add_primitive(Disk(point, radius, angle, options))
|
|
365
|
+
if options['legend_label']:
|
|
366
|
+
g.legend(True)
|
|
367
|
+
g._legend_colors = [options['legend_color']]
|
|
368
|
+
if len(point) == 2:
|
|
369
|
+
return g
|
|
370
|
+
elif len(point) == 3:
|
|
371
|
+
return g[0].plot3d(z=point[2])
|
|
372
|
+
raise ValueError('the center point of a plotted disk should have '
|
|
373
|
+
'two or three coordinates')
|