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
sage/plot/matrix_plot.py
ADDED
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-plot
|
|
2
|
+
"""
|
|
3
|
+
Matrix plots
|
|
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
|
+
#
|
|
10
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
11
|
+
#
|
|
12
|
+
# This code is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
15
|
+
# General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# The full text of the GPL is available at:
|
|
18
|
+
#
|
|
19
|
+
# https://www.gnu.org/licenses/
|
|
20
|
+
# ****************************************************************************
|
|
21
|
+
|
|
22
|
+
from sage.plot.primitive import GraphicPrimitive
|
|
23
|
+
from sage.misc.decorators import options, suboptions
|
|
24
|
+
from sage.plot.colors import get_cmap
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class MatrixPlot(GraphicPrimitive):
|
|
28
|
+
"""
|
|
29
|
+
Primitive class for the matrix plot graphics type. See
|
|
30
|
+
``matrix_plot?`` for help actually doing matrix plots.
|
|
31
|
+
|
|
32
|
+
INPUT:
|
|
33
|
+
|
|
34
|
+
- ``xy_data_array`` -- list of lists giving matrix values corresponding to
|
|
35
|
+
the grid
|
|
36
|
+
|
|
37
|
+
- ``xrange`` -- tuple of 2 floats indicating range for horizontal direction
|
|
38
|
+
(number of columns in the matrix). If ``None``, the defaults are used as
|
|
39
|
+
indicated in :func:`matrix_plot`.
|
|
40
|
+
|
|
41
|
+
- ``yrange`` -- tuple of 2 floats indicating range for vertical direction
|
|
42
|
+
(number of rows in the matrix). If ``None``, the defaults are used as
|
|
43
|
+
indicated in :func:`matrix_plot`.
|
|
44
|
+
|
|
45
|
+
- ``options`` -- dictionary of valid plot options to pass to constructor
|
|
46
|
+
|
|
47
|
+
EXAMPLES:
|
|
48
|
+
|
|
49
|
+
Note this should normally be used indirectly via :func:`matrix_plot`::
|
|
50
|
+
|
|
51
|
+
sage: from sage.plot.matrix_plot import MatrixPlot
|
|
52
|
+
sage: M = MatrixPlot([[1,3],[2,4]],(1,2),(2,3),options={'cmap':'winter'})
|
|
53
|
+
sage: M
|
|
54
|
+
MatrixPlot defined by a 2 x 2 data grid
|
|
55
|
+
sage: M.yrange
|
|
56
|
+
(2, 3)
|
|
57
|
+
sage: M.xy_data_array
|
|
58
|
+
[[1, 3], [2, 4]]
|
|
59
|
+
sage: M.options()
|
|
60
|
+
{'cmap': 'winter'}
|
|
61
|
+
|
|
62
|
+
Extra options will get passed on to :meth:`~Graphics.show`, as long as they are valid::
|
|
63
|
+
|
|
64
|
+
sage: matrix_plot([[1, 0], [0, 1]], fontsize=10)
|
|
65
|
+
Graphics object consisting of 1 graphics primitive
|
|
66
|
+
sage: matrix_plot([[1, 0], [0, 1]]).show(fontsize=10) # These are equivalent
|
|
67
|
+
|
|
68
|
+
TESTS:
|
|
69
|
+
|
|
70
|
+
We test creating a matrix plot::
|
|
71
|
+
|
|
72
|
+
sage: matrix_plot([[mod(i,5)^j for i in range(5)] for j in range(1,6)])
|
|
73
|
+
Graphics object consisting of 1 graphics primitive
|
|
74
|
+
"""
|
|
75
|
+
def __init__(self, xy_data_array, xrange, yrange, options):
|
|
76
|
+
"""
|
|
77
|
+
Initialize base class MatrixPlot.
|
|
78
|
+
|
|
79
|
+
EXAMPLES::
|
|
80
|
+
|
|
81
|
+
sage: M = matrix_plot([[mod(i,5)^j for i in range(5)] for j in range(1,6)], cmap='jet')
|
|
82
|
+
sage: M[0].get_minmax_data()
|
|
83
|
+
{'xmax': 4.5, 'xmin': -0.5, 'ymax': 4.5, 'ymin': -0.5}
|
|
84
|
+
sage: M[0].options()['cmap']
|
|
85
|
+
'jet'
|
|
86
|
+
sage: M[0].xy_array_row
|
|
87
|
+
5
|
|
88
|
+
"""
|
|
89
|
+
self.xrange = xrange
|
|
90
|
+
self.yrange = yrange
|
|
91
|
+
self.xy_data_array = xy_data_array
|
|
92
|
+
if hasattr(xy_data_array, 'shape'):
|
|
93
|
+
self.xy_array_row = xy_data_array.shape[0]
|
|
94
|
+
self.xy_array_col = xy_data_array.shape[1]
|
|
95
|
+
else:
|
|
96
|
+
self.xy_array_row = len(xy_data_array)
|
|
97
|
+
self.xy_array_col = len(xy_data_array[0])
|
|
98
|
+
GraphicPrimitive.__init__(self, options)
|
|
99
|
+
|
|
100
|
+
def get_minmax_data(self):
|
|
101
|
+
"""
|
|
102
|
+
Return a dictionary with the bounding box data.
|
|
103
|
+
|
|
104
|
+
EXAMPLES::
|
|
105
|
+
|
|
106
|
+
sage: m = matrix_plot(matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]]))[0]
|
|
107
|
+
sage: list(sorted(m.get_minmax_data().items()))
|
|
108
|
+
[('xmax', 3.5), ('xmin', -0.5), ('ymax', 2.5), ('ymin', -0.5)]
|
|
109
|
+
|
|
110
|
+
TESTS:
|
|
111
|
+
|
|
112
|
+
We verify that :issue:`27891` is fixed::
|
|
113
|
+
|
|
114
|
+
sage: p = matrix_plot(identity_matrix(5)) + point((2, 2), zorder=1)
|
|
115
|
+
sage: sorted(p.get_minmax_data().items())
|
|
116
|
+
[('xmax', 4.5), ('xmin', -0.5), ('ymax', 4.5), ('ymin', -0.5)]
|
|
117
|
+
"""
|
|
118
|
+
from sage.plot.plot import minmax_data
|
|
119
|
+
xrange = self.xrange
|
|
120
|
+
yrange = self.yrange
|
|
121
|
+
# if xrange/yrange are not specified, add offset to the matrix so that,
|
|
122
|
+
# for example, the square representing the (0,0) entry is centered on
|
|
123
|
+
# the origin.
|
|
124
|
+
if not xrange:
|
|
125
|
+
xrange = (-.5, self.xy_array_col - .5)
|
|
126
|
+
if not yrange:
|
|
127
|
+
yrange = (-.5, self.xy_array_row - .5)
|
|
128
|
+
return minmax_data(xrange, yrange, dict=True)
|
|
129
|
+
|
|
130
|
+
def _allowed_options(self):
|
|
131
|
+
"""
|
|
132
|
+
Return the allowed options for the MatrixPlot class.
|
|
133
|
+
|
|
134
|
+
EXAMPLES::
|
|
135
|
+
|
|
136
|
+
sage: M = matrix_plot([[sin(i*j) for i in range(5)] for j in range(5)]) # needs sage.symbolic
|
|
137
|
+
sage: isinstance(M[0]._allowed_options(), dict) # needs sage.symbolic
|
|
138
|
+
True
|
|
139
|
+
"""
|
|
140
|
+
return {'cmap':"""the name of a predefined colormap,
|
|
141
|
+
a list of colors, or an instance of a
|
|
142
|
+
matplotlib Colormap. Type: import matplotlib.cm; matplotlib.cm.datad.keys()
|
|
143
|
+
for available colormap names.""",
|
|
144
|
+
'colorbar': "Include a colorbar indicating the levels (dense matrices only)",
|
|
145
|
+
'colorbar_options': "a dictionary of options for colorbars",
|
|
146
|
+
'zorder':"The layer level in which to draw",
|
|
147
|
+
'marker':"The marker for sparse plots",
|
|
148
|
+
'markersize':"The marker size for sparse plots",
|
|
149
|
+
'norm': "The normalization function",
|
|
150
|
+
'vmin': "The minimum value",
|
|
151
|
+
'vmax': "The maximum value",
|
|
152
|
+
'flip_y': "If False, draw the matrix with the first row on the bottom of the graph",
|
|
153
|
+
'subdivisions': "If True, draw subdivisions of the matrix",
|
|
154
|
+
'subdivision_options': "Options (boundaries and style) of the subdivisions"}
|
|
155
|
+
|
|
156
|
+
def _repr_(self):
|
|
157
|
+
"""
|
|
158
|
+
String representation of MatrixPlot primitive.
|
|
159
|
+
|
|
160
|
+
EXAMPLES::
|
|
161
|
+
|
|
162
|
+
sage: M = matrix_plot([[sin(i*j) for i in range(5)] for j in range(5)]) # needs sage.symbolic
|
|
163
|
+
sage: m = M[0]; m # needs sage.symbolic
|
|
164
|
+
MatrixPlot defined by a 5 x 5 data grid
|
|
165
|
+
"""
|
|
166
|
+
return "MatrixPlot defined by a {} x {} data grid".format(self.xy_array_row, self.xy_array_col)
|
|
167
|
+
|
|
168
|
+
def _render_on_subplot(self, subplot):
|
|
169
|
+
"""
|
|
170
|
+
TESTS::
|
|
171
|
+
|
|
172
|
+
sage: matrix_plot(random_matrix(RDF, 50), cmap='jet')
|
|
173
|
+
Graphics object consisting of 1 graphics primitive
|
|
174
|
+
"""
|
|
175
|
+
options = self.options()
|
|
176
|
+
cmap = get_cmap(options.pop('cmap',None))
|
|
177
|
+
flip_y = options['flip_y']
|
|
178
|
+
|
|
179
|
+
norm = options['norm']
|
|
180
|
+
|
|
181
|
+
if norm == 'value':
|
|
182
|
+
import matplotlib
|
|
183
|
+
norm = matplotlib.colors.NoNorm()
|
|
184
|
+
|
|
185
|
+
lim = self.get_minmax_data()
|
|
186
|
+
if options['subdivisions']:
|
|
187
|
+
subdiv_options = options['subdivision_options']
|
|
188
|
+
if isinstance(subdiv_options['boundaries'], (list, tuple)):
|
|
189
|
+
rowsub,colsub = subdiv_options['boundaries']
|
|
190
|
+
else:
|
|
191
|
+
rowsub = subdiv_options['boundaries']
|
|
192
|
+
colsub = subdiv_options['boundaries']
|
|
193
|
+
if isinstance(subdiv_options['style'], (list, tuple)):
|
|
194
|
+
rowstyle,colstyle = subdiv_options['style']
|
|
195
|
+
else:
|
|
196
|
+
rowstyle = subdiv_options['style']
|
|
197
|
+
colstyle = subdiv_options['style']
|
|
198
|
+
if rowstyle is None:
|
|
199
|
+
rowstyle = {}
|
|
200
|
+
if colstyle is None:
|
|
201
|
+
colstyle = {}
|
|
202
|
+
|
|
203
|
+
# Make line objects for subdivisions
|
|
204
|
+
from .line import line2d
|
|
205
|
+
# First draw horizontal lines representing row subdivisions
|
|
206
|
+
for y in rowsub:
|
|
207
|
+
y = lim['ymin'] + ((lim['ymax'] - lim['ymin'])
|
|
208
|
+
* y / self.xy_array_row)
|
|
209
|
+
l = line2d([(lim['xmin'], y), (lim['xmax'], y)], **rowstyle)[0]
|
|
210
|
+
l._render_on_subplot(subplot)
|
|
211
|
+
for x in colsub:
|
|
212
|
+
x = lim['xmin'] + ((lim['xmax'] - lim['xmin'])
|
|
213
|
+
* x / self.xy_array_col)
|
|
214
|
+
l = line2d([(x, lim['ymin']), (x, lim['ymax'])], **colstyle)[0]
|
|
215
|
+
l._render_on_subplot(subplot)
|
|
216
|
+
|
|
217
|
+
if hasattr(self.xy_data_array, 'tocoo'):
|
|
218
|
+
# Sparse matrix -- use spy
|
|
219
|
+
opts = options.copy()
|
|
220
|
+
for opt in ['vmin', 'vmax', 'norm', 'flip_y', 'subdivisions',
|
|
221
|
+
'subdivision_options', 'colorbar', 'colorbar_options']:
|
|
222
|
+
del opts[opt]
|
|
223
|
+
subplot.spy(self.xy_data_array, **opts)
|
|
224
|
+
else:
|
|
225
|
+
extent = (lim['xmin'], lim['xmax'],
|
|
226
|
+
lim['ymax' if flip_y else 'ymin'],
|
|
227
|
+
lim['ymin' if flip_y else 'ymax'])
|
|
228
|
+
opts = {'cmap': cmap, 'interpolation': 'nearest',
|
|
229
|
+
'aspect': 'equal', 'norm': norm,
|
|
230
|
+
'vmin': options['vmin'], 'vmax': options['vmax'],
|
|
231
|
+
'origin': ('upper' if flip_y else 'lower'),
|
|
232
|
+
'extent': extent, 'zorder': options.get('zorder')}
|
|
233
|
+
image = subplot.imshow(self.xy_data_array, **opts)
|
|
234
|
+
|
|
235
|
+
if options.get('colorbar', False):
|
|
236
|
+
colorbar_options = options['colorbar_options']
|
|
237
|
+
from matplotlib import colorbar
|
|
238
|
+
cax,kwds = colorbar.make_axes_gridspec(subplot, **colorbar_options)
|
|
239
|
+
colorbar.Colorbar(cax, image, **kwds)
|
|
240
|
+
|
|
241
|
+
if flip_y:
|
|
242
|
+
subplot.xaxis.tick_top()
|
|
243
|
+
else:
|
|
244
|
+
subplot.xaxis.tick_bottom()
|
|
245
|
+
subplot.xaxis.set_ticks_position('both') # only tick marks, not tick labels
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
@suboptions('colorbar', orientation='vertical', format=None)
|
|
249
|
+
@suboptions('subdivision',boundaries=None, style=None)
|
|
250
|
+
@options(aspect_ratio=1, axes=False, cmap='Greys', colorbar=False,
|
|
251
|
+
frame=True, marker='.', norm=None, flip_y=True,
|
|
252
|
+
subdivisions=False, ticks_integer=True, vmin=None, vmax=None)
|
|
253
|
+
def matrix_plot(mat, xrange=None, yrange=None, **options):
|
|
254
|
+
r"""
|
|
255
|
+
A plot of a given matrix or 2D array.
|
|
256
|
+
|
|
257
|
+
If the matrix is sparse, colors only indicate whether an element is
|
|
258
|
+
nonzero or zero, so the plot represents the sparsity pattern of the
|
|
259
|
+
matrix.
|
|
260
|
+
|
|
261
|
+
If the matrix is dense, each matrix element is given a different
|
|
262
|
+
color value depending on its relative size compared to the other
|
|
263
|
+
elements in the matrix.
|
|
264
|
+
|
|
265
|
+
The default is for the lowest number to be black and the highest
|
|
266
|
+
number to be white in a greyscale pattern; see the information about
|
|
267
|
+
normalizing below. To reverse this, use ``cmap='Greys'``.
|
|
268
|
+
|
|
269
|
+
The tick marks drawn on the frame axes denote the row numbers
|
|
270
|
+
(vertical ticks) and the column numbers (horizontal ticks) of the
|
|
271
|
+
matrix.
|
|
272
|
+
|
|
273
|
+
INPUT:
|
|
274
|
+
|
|
275
|
+
- ``mat`` -- a 2D matrix or array
|
|
276
|
+
|
|
277
|
+
- ``xrange`` -- (default: ``None``) tuple of the horizontal extent
|
|
278
|
+
``(xmin, xmax)`` of the bounding box in which to draw the matrix. The
|
|
279
|
+
image is stretched individually along x and y to fill the box.
|
|
280
|
+
|
|
281
|
+
If ``None``, the extent is determined by the following conditions. Matrix
|
|
282
|
+
entries have unit size in data coordinates. Their centers are on integer
|
|
283
|
+
coordinates, and their center coordinates range from 0 to columns-1
|
|
284
|
+
horizontally and from 0 to rows-1 vertically.
|
|
285
|
+
|
|
286
|
+
If the matrix is sparse, this keyword is ignored.
|
|
287
|
+
|
|
288
|
+
- ``yrange`` -- (default: ``None``) tuple of the vertical extent
|
|
289
|
+
``(ymin, ymax)`` of the bounding box in which to draw the matrix.
|
|
290
|
+
See ``xrange`` for details.
|
|
291
|
+
|
|
292
|
+
The following input must all be passed in as named parameters, if
|
|
293
|
+
default not used:
|
|
294
|
+
|
|
295
|
+
- ``cmap`` -- a colormap (default: ``'Greys'``); the name of a predefined
|
|
296
|
+
colormap, a list of colors, or an instance of a matplotlib Colormap
|
|
297
|
+
|
|
298
|
+
The list of predefined color maps can be visualized in `matplotlib's
|
|
299
|
+
documentation
|
|
300
|
+
<https://matplotlib.org/examples/color/colormaps_reference.html>`__. You
|
|
301
|
+
can also type ``import matplotlib.cm; matplotlib.cm.datad.keys()`` to list
|
|
302
|
+
their names.
|
|
303
|
+
|
|
304
|
+
- ``colorbar`` -- boolean (default: ``False``); show a colorbar or not
|
|
305
|
+
(dense matrices only)
|
|
306
|
+
|
|
307
|
+
The following options are used to adjust the style and placement
|
|
308
|
+
of colorbars. They have no effect if a colorbar is not shown.
|
|
309
|
+
|
|
310
|
+
- ``colorbar_orientation`` -- string (default: ``'vertical'``);
|
|
311
|
+
controls placement of the colorbar, can be either 'vertical'
|
|
312
|
+
or 'horizontal'
|
|
313
|
+
|
|
314
|
+
- ``colorbar_format`` -- a format string, this is used to format
|
|
315
|
+
the colorbar labels
|
|
316
|
+
|
|
317
|
+
- ``colorbar_options`` -- dictionary of options for the matplotlib
|
|
318
|
+
colorbar API. Documentation for the :mod:`matplotlib.colorbar` module
|
|
319
|
+
has details.
|
|
320
|
+
|
|
321
|
+
- ``norm`` -- if ``None`` (default), the value range is scaled to the interval
|
|
322
|
+
[0,1]. If 'value', then the actual value is used with no
|
|
323
|
+
scaling. A :class:`matplotlib.colors.Normalize` instance may
|
|
324
|
+
also passed.
|
|
325
|
+
|
|
326
|
+
- ``vmin`` -- the minimum value (values below this are set to this value)
|
|
327
|
+
|
|
328
|
+
- ``vmax`` -- the maximum value (values above this are set to this value)
|
|
329
|
+
|
|
330
|
+
- ``flip_y`` -- boolean (default: ``True``); if ``False``, the first row of the
|
|
331
|
+
matrix is on the bottom of the graph. Otherwise, the first row is on the
|
|
332
|
+
top of the graph.
|
|
333
|
+
|
|
334
|
+
- ``subdivisions`` -- if ``True``, plot the subdivisions of the matrix as lines
|
|
335
|
+
|
|
336
|
+
- ``subdivision_boundaries`` -- list of lists in the form
|
|
337
|
+
``[row_subdivisions, column_subdivisions]``, which specifies
|
|
338
|
+
the row and column subdivisions to use. If not specified,
|
|
339
|
+
defaults to the matrix subdivisions
|
|
340
|
+
|
|
341
|
+
- ``subdivision_style`` -- dictionary of properties passed
|
|
342
|
+
on to the :func:`~sage.plot.line.line2d` command for plotting
|
|
343
|
+
subdivisions. If this is a two-element list or tuple, then it
|
|
344
|
+
specifies the styles of row and column divisions, respectively.
|
|
345
|
+
|
|
346
|
+
EXAMPLES:
|
|
347
|
+
|
|
348
|
+
A matrix over `\ZZ` colored with different grey levels::
|
|
349
|
+
|
|
350
|
+
sage: matrix_plot(matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]]))
|
|
351
|
+
Graphics object consisting of 1 graphics primitive
|
|
352
|
+
|
|
353
|
+
.. PLOT::
|
|
354
|
+
|
|
355
|
+
P = matrix_plot(matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]]))
|
|
356
|
+
sphinx_plot(P)
|
|
357
|
+
|
|
358
|
+
Here we make a random matrix over `\RR` and use ``cmap='hsv'``
|
|
359
|
+
to color the matrix elements different RGB colors::
|
|
360
|
+
|
|
361
|
+
sage: matrix_plot(random_matrix(RDF, 50), cmap='hsv')
|
|
362
|
+
Graphics object consisting of 1 graphics primitive
|
|
363
|
+
|
|
364
|
+
By default, entries are scaled to the interval [0,1] before
|
|
365
|
+
determining colors from the color map. That means the two plots
|
|
366
|
+
below are the same::
|
|
367
|
+
|
|
368
|
+
sage: P = matrix_plot(matrix(2,[1,1,3,3]))
|
|
369
|
+
sage: Q = matrix_plot(matrix(2,[2,2,3,3]))
|
|
370
|
+
sage: P; Q
|
|
371
|
+
Graphics object consisting of 1 graphics primitive
|
|
372
|
+
Graphics object consisting of 1 graphics primitive
|
|
373
|
+
|
|
374
|
+
However, we can specify which values scale to 0 or 1 with the
|
|
375
|
+
``vmin`` and ``vmax`` parameters (values outside the range are
|
|
376
|
+
clipped). The two plots below are now distinguished::
|
|
377
|
+
|
|
378
|
+
sage: P = matrix_plot(matrix(2,[1,1,3,3]), vmin=0, vmax=3, colorbar=True)
|
|
379
|
+
sage: Q = matrix_plot(matrix(2,[2,2,3,3]), vmin=0, vmax=3, colorbar=True)
|
|
380
|
+
sage: P; Q
|
|
381
|
+
Graphics object consisting of 1 graphics primitive
|
|
382
|
+
Graphics object consisting of 1 graphics primitive
|
|
383
|
+
|
|
384
|
+
We can also specify a norm function of 'value', which means that
|
|
385
|
+
there is no scaling performed::
|
|
386
|
+
|
|
387
|
+
sage: matrix_plot(random_matrix(ZZ,10)*.05, norm='value', colorbar=True)
|
|
388
|
+
Graphics object consisting of 1 graphics primitive
|
|
389
|
+
|
|
390
|
+
Matrix subdivisions can be plotted as well::
|
|
391
|
+
|
|
392
|
+
sage: m=random_matrix(RR,10)
|
|
393
|
+
sage: m.subdivide([2,4],[6,8])
|
|
394
|
+
sage: matrix_plot(m, subdivisions=True,
|
|
395
|
+
....: subdivision_style=dict(color='red',thickness=3))
|
|
396
|
+
Graphics object consisting of 1 graphics primitive
|
|
397
|
+
|
|
398
|
+
You can also specify your own subdivisions and separate styles
|
|
399
|
+
for row or column subdivisions::
|
|
400
|
+
|
|
401
|
+
sage: m=random_matrix(RR,10)
|
|
402
|
+
sage: matrix_plot(m, subdivisions=True, subdivision_boundaries=[[2,4],[6,8]],
|
|
403
|
+
....: subdivision_style=[dict(color='red',thickness=3),
|
|
404
|
+
....: dict(linestyle='--',thickness=6)])
|
|
405
|
+
Graphics object consisting of 1 graphics primitive
|
|
406
|
+
|
|
407
|
+
Generally matrices are plotted with the (0,0) entry in the upper
|
|
408
|
+
left. However, sometimes if we are plotting an image, we'd like
|
|
409
|
+
the (0,0) entry to be in the lower left. We can do that with the
|
|
410
|
+
``flip_y`` argument::
|
|
411
|
+
|
|
412
|
+
sage: matrix_plot(identity_matrix(100), flip_y=False)
|
|
413
|
+
Graphics object consisting of 1 graphics primitive
|
|
414
|
+
|
|
415
|
+
A custom bounding box in which to draw the matrix can be specified using
|
|
416
|
+
the ``xrange`` and ``yrange`` arguments::
|
|
417
|
+
|
|
418
|
+
sage: P = matrix_plot(identity_matrix(10), xrange=(0, pi), yrange=(-pi, 0)); P # needs sage.symbolic
|
|
419
|
+
Graphics object consisting of 1 graphics primitive
|
|
420
|
+
sage: P.get_minmax_data() # needs sage.symbolic
|
|
421
|
+
{'xmax': 3.14159..., 'xmin': 0.0, 'ymax': 0.0, 'ymin': -3.14159...}
|
|
422
|
+
|
|
423
|
+
If the horizontal and vertical dimension of the image are very different,
|
|
424
|
+
the default ``aspect_ratio=1`` may be unsuitable and can be changed to
|
|
425
|
+
``automatic``::
|
|
426
|
+
|
|
427
|
+
sage: matrix_plot(random_matrix(RDF, 2, 2), (-100, 100), (0, 1),
|
|
428
|
+
....: aspect_ratio='automatic')
|
|
429
|
+
Graphics object consisting of 1 graphics primitive
|
|
430
|
+
|
|
431
|
+
Another random plot, but over `\GF{389}`::
|
|
432
|
+
|
|
433
|
+
sage: m = random_matrix(GF(389), 10) # needs sage.rings.finite_rings
|
|
434
|
+
sage: matrix_plot(m, cmap='Oranges') # needs sage.rings.finite_rings
|
|
435
|
+
Graphics object consisting of 1 graphics primitive
|
|
436
|
+
|
|
437
|
+
It also works if you lift it to the polynomial ring::
|
|
438
|
+
|
|
439
|
+
sage: matrix_plot(m.change_ring(GF(389)['x']), cmap='Oranges') # needs sage.rings.finite_rings
|
|
440
|
+
Graphics object consisting of 1 graphics primitive
|
|
441
|
+
|
|
442
|
+
We have several options for colorbars::
|
|
443
|
+
|
|
444
|
+
sage: matrix_plot(random_matrix(RDF, 50), colorbar=True,
|
|
445
|
+
....: colorbar_orientation='horizontal')
|
|
446
|
+
Graphics object consisting of 1 graphics primitive
|
|
447
|
+
|
|
448
|
+
::
|
|
449
|
+
|
|
450
|
+
sage: matrix_plot(random_matrix(RDF, 50), colorbar=True, colorbar_format='%.3f')
|
|
451
|
+
Graphics object consisting of 1 graphics primitive
|
|
452
|
+
|
|
453
|
+
The length of a color bar and the length of the adjacent
|
|
454
|
+
matrix plot dimension may be quite different. This example
|
|
455
|
+
shows how to adjust the length of the colorbar by passing a
|
|
456
|
+
dictionary of options to the matplotlib colorbar routines. ::
|
|
457
|
+
|
|
458
|
+
sage: m = random_matrix(ZZ, 40, 80, x=-10, y=10)
|
|
459
|
+
sage: m.plot(colorbar=True, colorbar_orientation='vertical',
|
|
460
|
+
....: colorbar_options={'shrink':0.50})
|
|
461
|
+
Graphics object consisting of 1 graphics primitive
|
|
462
|
+
|
|
463
|
+
Here we plot a random sparse matrix::
|
|
464
|
+
|
|
465
|
+
sage: sparse = matrix(dict(((randint(0, 10), randint(0, 10)), 1)
|
|
466
|
+
....: for i in range(100)))
|
|
467
|
+
sage: matrix_plot(sparse)
|
|
468
|
+
Graphics object consisting of 1 graphics primitive
|
|
469
|
+
|
|
470
|
+
::
|
|
471
|
+
|
|
472
|
+
sage: A = random_matrix(ZZ, 100000, density=.00001, sparse=True)
|
|
473
|
+
sage: matrix_plot(A, marker=',')
|
|
474
|
+
Graphics object consisting of 1 graphics primitive
|
|
475
|
+
|
|
476
|
+
As with dense matrices, sparse matrix entries are automatically
|
|
477
|
+
converted to floating point numbers before plotting. Thus the
|
|
478
|
+
following works::
|
|
479
|
+
|
|
480
|
+
sage: b = random_matrix(GF(2), 200, sparse=True, density=0.01) # needs sage.rings.finite_rings
|
|
481
|
+
sage: matrix_plot(b) # needs sage.rings.finite_rings
|
|
482
|
+
Graphics object consisting of 1 graphics primitive
|
|
483
|
+
|
|
484
|
+
While this returns an error::
|
|
485
|
+
|
|
486
|
+
sage: b = random_matrix(CDF, 200, sparse=True, density=0.01)
|
|
487
|
+
sage: matrix_plot(b)
|
|
488
|
+
Traceback (most recent call last):
|
|
489
|
+
...
|
|
490
|
+
ValueError: cannot convert entries to floating point numbers
|
|
491
|
+
|
|
492
|
+
To plot the absolute value of a complex matrix, use the
|
|
493
|
+
``apply_map`` method::
|
|
494
|
+
|
|
495
|
+
sage: b = random_matrix(CDF, 200, sparse=True, density=0.01)
|
|
496
|
+
sage: matrix_plot(b.apply_map(abs))
|
|
497
|
+
Graphics object consisting of 1 graphics primitive
|
|
498
|
+
|
|
499
|
+
Plotting lists of lists also works::
|
|
500
|
+
|
|
501
|
+
sage: matrix_plot([[1,3,5,1],[2,4,5,6],[1,3,5,7]])
|
|
502
|
+
Graphics object consisting of 1 graphics primitive
|
|
503
|
+
|
|
504
|
+
As does plotting of NumPy arrays::
|
|
505
|
+
|
|
506
|
+
sage: import numpy # needs numpy
|
|
507
|
+
sage: matrix_plot(numpy.random.rand(10, 10)) # needs numpy
|
|
508
|
+
Graphics object consisting of 1 graphics primitive
|
|
509
|
+
|
|
510
|
+
A plot title can be added to the matrix plot.::
|
|
511
|
+
|
|
512
|
+
sage: matrix_plot(identity_matrix(50), flip_y=False, title='not identity')
|
|
513
|
+
Graphics object consisting of 1 graphics primitive
|
|
514
|
+
|
|
515
|
+
The title position is adjusted upwards if the ``flip_y`` keyword is set
|
|
516
|
+
to ``True`` (this is the default).::
|
|
517
|
+
|
|
518
|
+
sage: matrix_plot(identity_matrix(50), title='identity')
|
|
519
|
+
Graphics object consisting of 1 graphics primitive
|
|
520
|
+
|
|
521
|
+
TESTS::
|
|
522
|
+
|
|
523
|
+
sage: P.<t> = RR[]
|
|
524
|
+
sage: M = random_matrix(P, 3, 3)
|
|
525
|
+
sage: (i,j) = (ZZ.random_element(3), ZZ.random_element(3))
|
|
526
|
+
sage: M[i,j] = P.random_element(degree=(1,5)) # always nonconstant
|
|
527
|
+
sage: matrix_plot(M)
|
|
528
|
+
Traceback (most recent call last):
|
|
529
|
+
...
|
|
530
|
+
TypeError: cannot convert nonconstant polynomial
|
|
531
|
+
|
|
532
|
+
::
|
|
533
|
+
|
|
534
|
+
sage: matrix_plot([1,2,3])
|
|
535
|
+
Traceback (most recent call last):
|
|
536
|
+
...
|
|
537
|
+
TypeError: mat must be a Matrix or a two dimensional array
|
|
538
|
+
|
|
539
|
+
::
|
|
540
|
+
|
|
541
|
+
sage: matrix_plot([[sin(x), cos(x)], [1, 0]]) # needs sage.symbolic
|
|
542
|
+
Traceback (most recent call last):
|
|
543
|
+
...
|
|
544
|
+
TypeError: mat must be a Matrix or a two dimensional array
|
|
545
|
+
|
|
546
|
+
Test that sparse matrices also work with subdivisions::
|
|
547
|
+
|
|
548
|
+
sage: matrix_plot(sparse, subdivisions=True, subdivision_boundaries=[[2,4],[6,8]])
|
|
549
|
+
Graphics object consisting of 1 graphics primitive
|
|
550
|
+
|
|
551
|
+
Test that matrix plots have aspect ratio one (see :issue:`15315`)::
|
|
552
|
+
|
|
553
|
+
sage: P = matrix_plot(random_matrix(RDF, 5))
|
|
554
|
+
sage: P.aspect_ratio()
|
|
555
|
+
1
|
|
556
|
+
|
|
557
|
+
The origin keyword is deprecated::
|
|
558
|
+
|
|
559
|
+
sage: matrix_plot(identity_matrix(100), origin='lower')
|
|
560
|
+
doctest:...: DeprecationWarning: the option 'origin' is replaced by 'flip_y'
|
|
561
|
+
See https://github.com/sagemath/sage/issues/27891 for details.
|
|
562
|
+
Graphics object consisting of 1 graphics primitive
|
|
563
|
+
"""
|
|
564
|
+
if 'origin' in options:
|
|
565
|
+
from sage.misc.superseded import deprecation
|
|
566
|
+
deprecation(27891, "the option 'origin' is replaced by 'flip_y'")
|
|
567
|
+
options['flip_y'] = (options['origin'] != 'lower')
|
|
568
|
+
del options['origin']
|
|
569
|
+
|
|
570
|
+
import numpy as np
|
|
571
|
+
import scipy.sparse as scipysparse
|
|
572
|
+
from sage.plot.all import Graphics
|
|
573
|
+
from sage.structure.element import Matrix
|
|
574
|
+
from sage.rings.real_double import RDF
|
|
575
|
+
orig_mat = mat
|
|
576
|
+
if isinstance(mat, Matrix):
|
|
577
|
+
sparse = mat.is_sparse()
|
|
578
|
+
if sparse:
|
|
579
|
+
entries = list(mat._dict().items())
|
|
580
|
+
try:
|
|
581
|
+
data = np.asarray([d for _,d in entries], dtype=float)
|
|
582
|
+
except Exception:
|
|
583
|
+
raise ValueError("cannot convert entries to floating point numbers")
|
|
584
|
+
positions = np.asarray([[row for (row,col),_ in entries],
|
|
585
|
+
[col for (row,col),_ in entries]], dtype=int)
|
|
586
|
+
mat = scipysparse.coo_matrix((data,positions), shape=(mat.nrows(), mat.ncols()))
|
|
587
|
+
else:
|
|
588
|
+
mat = mat.change_ring(RDF).numpy()
|
|
589
|
+
elif hasattr(mat, 'tocoo'):
|
|
590
|
+
sparse = True
|
|
591
|
+
else:
|
|
592
|
+
sparse = False
|
|
593
|
+
|
|
594
|
+
try:
|
|
595
|
+
if sparse:
|
|
596
|
+
xy_data_array = mat
|
|
597
|
+
else:
|
|
598
|
+
xy_data_array = np.asarray(mat, dtype=float)
|
|
599
|
+
except TypeError:
|
|
600
|
+
raise TypeError("mat must be a Matrix or a two dimensional array")
|
|
601
|
+
except ValueError:
|
|
602
|
+
raise ValueError("cannot convert entries to floating point numbers")
|
|
603
|
+
|
|
604
|
+
if len(xy_data_array.shape) < 2:
|
|
605
|
+
raise TypeError("mat must be a Matrix or a two dimensional array")
|
|
606
|
+
|
|
607
|
+
# Sparse matrices are not plotted with imshow, so extent is not supported,
|
|
608
|
+
# hence we ignore custom bounds.
|
|
609
|
+
if sparse:
|
|
610
|
+
xrange = None
|
|
611
|
+
yrange = None
|
|
612
|
+
if xrange:
|
|
613
|
+
xrange = tuple(float(v) for v in xrange)
|
|
614
|
+
if yrange:
|
|
615
|
+
yrange = tuple(float(v) for v in yrange)
|
|
616
|
+
|
|
617
|
+
if options['subdivisions'] and options['subdivision_options']['boundaries'] is None:
|
|
618
|
+
options['subdivision_options']['boundaries'] = orig_mat.get_subdivisions()
|
|
619
|
+
|
|
620
|
+
# Custom position the title. Otherwise it overlaps with tick labels
|
|
621
|
+
if options['flip_y'] and 'title_pos' not in options:
|
|
622
|
+
options['title_pos'] = (0.5, 1.05)
|
|
623
|
+
|
|
624
|
+
g = Graphics()
|
|
625
|
+
g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
|
|
626
|
+
# Keep flip_y for _render_on_subplot
|
|
627
|
+
options['flip_y'] = g._extra_kwds['flip_y']
|
|
628
|
+
g.add_primitive(MatrixPlot(xy_data_array, xrange, yrange, options))
|
|
629
|
+
return g
|