passagemath-polyhedra 10.6.31rc3__cp314-cp314-macosx_13_0_arm64.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-polyhedra might be problematic. Click here for more details.

Files changed (205) hide show
  1. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +368 -0
  2. passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +371 -0
  3. passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +205 -0
  4. passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +6 -0
  5. passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
  6. passagemath_polyhedra.dylibs/libgmp.10.dylib +0 -0
  7. sage/all__sagemath_polyhedra.py +50 -0
  8. sage/game_theory/all.py +8 -0
  9. sage/game_theory/catalog.py +6 -0
  10. sage/game_theory/catalog_normal_form_games.py +923 -0
  11. sage/game_theory/cooperative_game.py +844 -0
  12. sage/game_theory/matching_game.py +1181 -0
  13. sage/game_theory/normal_form_game.py +2697 -0
  14. sage/game_theory/parser.py +275 -0
  15. sage/geometry/all__sagemath_polyhedra.py +22 -0
  16. sage/geometry/cone.py +6940 -0
  17. sage/geometry/cone_catalog.py +847 -0
  18. sage/geometry/cone_critical_angles.py +1027 -0
  19. sage/geometry/convex_set.py +1119 -0
  20. sage/geometry/fan.py +3743 -0
  21. sage/geometry/fan_isomorphism.py +389 -0
  22. sage/geometry/fan_morphism.py +1884 -0
  23. sage/geometry/hasse_diagram.py +202 -0
  24. sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
  25. sage/geometry/hyperplane_arrangement/all.py +1 -0
  26. sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
  27. sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
  28. sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
  29. sage/geometry/hyperplane_arrangement/library.py +825 -0
  30. sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
  31. sage/geometry/hyperplane_arrangement/plot.py +520 -0
  32. sage/geometry/integral_points.py +35 -0
  33. sage/geometry/integral_points_generic_dense.cpython-314-darwin.so +0 -0
  34. sage/geometry/integral_points_generic_dense.pyx +7 -0
  35. sage/geometry/lattice_polytope.py +5894 -0
  36. sage/geometry/linear_expression.py +773 -0
  37. sage/geometry/newton_polygon.py +767 -0
  38. sage/geometry/point_collection.cpython-314-darwin.so +0 -0
  39. sage/geometry/point_collection.pyx +1008 -0
  40. sage/geometry/polyhedral_complex.py +2616 -0
  41. sage/geometry/polyhedron/all.py +8 -0
  42. sage/geometry/polyhedron/backend_cdd.py +460 -0
  43. sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
  44. sage/geometry/polyhedron/backend_field.py +347 -0
  45. sage/geometry/polyhedron/backend_normaliz.py +2503 -0
  46. sage/geometry/polyhedron/backend_number_field.py +168 -0
  47. sage/geometry/polyhedron/backend_polymake.py +765 -0
  48. sage/geometry/polyhedron/backend_ppl.py +582 -0
  49. sage/geometry/polyhedron/base.py +1206 -0
  50. sage/geometry/polyhedron/base0.py +1444 -0
  51. sage/geometry/polyhedron/base1.py +886 -0
  52. sage/geometry/polyhedron/base2.py +812 -0
  53. sage/geometry/polyhedron/base3.py +1845 -0
  54. sage/geometry/polyhedron/base4.py +1262 -0
  55. sage/geometry/polyhedron/base5.py +2700 -0
  56. sage/geometry/polyhedron/base6.py +1741 -0
  57. sage/geometry/polyhedron/base7.py +997 -0
  58. sage/geometry/polyhedron/base_QQ.py +1258 -0
  59. sage/geometry/polyhedron/base_RDF.py +98 -0
  60. sage/geometry/polyhedron/base_ZZ.py +934 -0
  61. sage/geometry/polyhedron/base_mutable.py +215 -0
  62. sage/geometry/polyhedron/base_number_field.py +122 -0
  63. sage/geometry/polyhedron/cdd_file_format.py +155 -0
  64. sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
  65. sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-darwin.so +0 -0
  66. sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
  67. sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
  68. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-darwin.so +0 -0
  69. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
  70. sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
  71. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-darwin.so +0 -0
  72. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
  73. sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
  74. sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
  75. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-darwin.so +0 -0
  76. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
  77. sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
  78. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-darwin.so +0 -0
  79. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
  80. sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
  81. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-darwin.so +0 -0
  82. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
  83. sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
  84. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-darwin.so +0 -0
  85. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
  86. sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
  87. sage/geometry/polyhedron/constructor.py +773 -0
  88. sage/geometry/polyhedron/double_description.py +753 -0
  89. sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
  90. sage/geometry/polyhedron/face.py +1060 -0
  91. sage/geometry/polyhedron/generating_function.py +1810 -0
  92. sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
  93. sage/geometry/polyhedron/library.py +3502 -0
  94. sage/geometry/polyhedron/misc.py +121 -0
  95. sage/geometry/polyhedron/modules/all.py +1 -0
  96. sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
  97. sage/geometry/polyhedron/palp_database.py +447 -0
  98. sage/geometry/polyhedron/parent.py +1279 -0
  99. sage/geometry/polyhedron/plot.py +1986 -0
  100. sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
  101. sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
  102. sage/geometry/polyhedron/representation.py +1723 -0
  103. sage/geometry/pseudolines.py +515 -0
  104. sage/geometry/relative_interior.py +445 -0
  105. sage/geometry/toric_plotter.py +1103 -0
  106. sage/geometry/triangulation/all.py +2 -0
  107. sage/geometry/triangulation/base.cpython-314-darwin.so +0 -0
  108. sage/geometry/triangulation/base.pyx +963 -0
  109. sage/geometry/triangulation/data.h +147 -0
  110. sage/geometry/triangulation/data.pxd +4 -0
  111. sage/geometry/triangulation/element.py +914 -0
  112. sage/geometry/triangulation/functions.h +10 -0
  113. sage/geometry/triangulation/functions.pxd +4 -0
  114. sage/geometry/triangulation/point_configuration.py +2256 -0
  115. sage/geometry/triangulation/triangulations.h +49 -0
  116. sage/geometry/triangulation/triangulations.pxd +7 -0
  117. sage/geometry/voronoi_diagram.py +319 -0
  118. sage/interfaces/all__sagemath_polyhedra.py +1 -0
  119. sage/interfaces/polymake.py +2028 -0
  120. sage/numerical/all.py +13 -0
  121. sage/numerical/all__sagemath_polyhedra.py +11 -0
  122. sage/numerical/backends/all.py +1 -0
  123. sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
  124. sage/numerical/backends/cvxopt_backend.cpython-314-darwin.so +0 -0
  125. sage/numerical/backends/cvxopt_backend.pyx +1006 -0
  126. sage/numerical/backends/cvxopt_backend_test.py +19 -0
  127. sage/numerical/backends/cvxopt_sdp_backend.cpython-314-darwin.so +0 -0
  128. sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
  129. sage/numerical/backends/cvxpy_backend.cpython-314-darwin.so +0 -0
  130. sage/numerical/backends/cvxpy_backend.pxd +41 -0
  131. sage/numerical/backends/cvxpy_backend.pyx +934 -0
  132. sage/numerical/backends/cvxpy_backend_test.py +13 -0
  133. sage/numerical/backends/generic_backend_test.py +24 -0
  134. sage/numerical/backends/interactivelp_backend.cpython-314-darwin.so +0 -0
  135. sage/numerical/backends/interactivelp_backend.pxd +36 -0
  136. sage/numerical/backends/interactivelp_backend.pyx +1231 -0
  137. sage/numerical/backends/interactivelp_backend_test.py +12 -0
  138. sage/numerical/backends/logging_backend.py +391 -0
  139. sage/numerical/backends/matrix_sdp_backend.cpython-314-darwin.so +0 -0
  140. sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
  141. sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
  142. sage/numerical/backends/ppl_backend.cpython-314-darwin.so +0 -0
  143. sage/numerical/backends/ppl_backend.pyx +1126 -0
  144. sage/numerical/backends/ppl_backend_test.py +13 -0
  145. sage/numerical/backends/scip_backend.cpython-314-darwin.so +0 -0
  146. sage/numerical/backends/scip_backend.pxd +22 -0
  147. sage/numerical/backends/scip_backend.pyx +1289 -0
  148. sage/numerical/backends/scip_backend_test.py +13 -0
  149. sage/numerical/interactive_simplex_method.py +5338 -0
  150. sage/numerical/knapsack.py +665 -0
  151. sage/numerical/linear_functions.cpython-314-darwin.so +0 -0
  152. sage/numerical/linear_functions.pxd +31 -0
  153. sage/numerical/linear_functions.pyx +1648 -0
  154. sage/numerical/linear_tensor.py +470 -0
  155. sage/numerical/linear_tensor_constraints.py +448 -0
  156. sage/numerical/linear_tensor_element.cpython-314-darwin.so +0 -0
  157. sage/numerical/linear_tensor_element.pxd +6 -0
  158. sage/numerical/linear_tensor_element.pyx +459 -0
  159. sage/numerical/mip.cpython-314-darwin.so +0 -0
  160. sage/numerical/mip.pxd +40 -0
  161. sage/numerical/mip.pyx +3667 -0
  162. sage/numerical/sdp.cpython-314-darwin.so +0 -0
  163. sage/numerical/sdp.pxd +39 -0
  164. sage/numerical/sdp.pyx +1433 -0
  165. sage/rings/all__sagemath_polyhedra.py +3 -0
  166. sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
  167. sage/rings/polynomial/omega.py +982 -0
  168. sage/schemes/all__sagemath_polyhedra.py +2 -0
  169. sage/schemes/toric/all.py +10 -0
  170. sage/schemes/toric/chow_group.py +1248 -0
  171. sage/schemes/toric/divisor.py +2082 -0
  172. sage/schemes/toric/divisor_class.cpython-314-darwin.so +0 -0
  173. sage/schemes/toric/divisor_class.pyx +322 -0
  174. sage/schemes/toric/fano_variety.py +1606 -0
  175. sage/schemes/toric/homset.py +650 -0
  176. sage/schemes/toric/ideal.py +451 -0
  177. sage/schemes/toric/library.py +1322 -0
  178. sage/schemes/toric/morphism.py +1958 -0
  179. sage/schemes/toric/points.py +1032 -0
  180. sage/schemes/toric/sheaf/all.py +1 -0
  181. sage/schemes/toric/sheaf/constructor.py +302 -0
  182. sage/schemes/toric/sheaf/klyachko.py +921 -0
  183. sage/schemes/toric/toric_subscheme.py +905 -0
  184. sage/schemes/toric/variety.py +3460 -0
  185. sage/schemes/toric/weierstrass.py +1078 -0
  186. sage/schemes/toric/weierstrass_covering.py +457 -0
  187. sage/schemes/toric/weierstrass_higher.py +288 -0
  188. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
  189. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
  190. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
  191. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
  192. sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
  193. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
  194. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
  195. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
  196. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
  197. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
  198. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
  199. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
  200. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
  201. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
  202. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
  203. sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
  204. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
  205. sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
@@ -0,0 +1,1103 @@
1
+ # sage_setup: distribution = sagemath-polyhedra
2
+ r"""
3
+ Toric plotter
4
+
5
+ This module provides a helper class :class:`ToricPlotter` for producing plots
6
+ of objects related to toric geometry. Default plotting objects can be adjusted
7
+ using :func:`options` and reset using :func:`reset_options`.
8
+
9
+ AUTHORS:
10
+
11
+ - Andrey Novoseltsev (2010-10-03): initial version, using some code bits by
12
+ Volker Braun.
13
+
14
+ EXAMPLES:
15
+
16
+ In most cases, this module is used indirectly, e.g. ::
17
+
18
+ sage: fan = toric_varieties.dP6().fan() # needs palp sage.graphs
19
+ sage: fan.plot() # needs palp sage.graphs sage.plot sage.symbolic
20
+ Graphics object consisting of 31 graphics primitives
21
+
22
+ You may change default plotting options as follows::
23
+
24
+ sage: toric_plotter.options("show_rays")
25
+ True
26
+ sage: toric_plotter.options(show_rays=False)
27
+ sage: toric_plotter.options("show_rays")
28
+ False
29
+ sage: fan.plot() # needs palp sage.graphs sage.plot sage.symbolic
30
+ Graphics object consisting of 19 graphics primitives
31
+ sage: toric_plotter.reset_options()
32
+ sage: toric_plotter.options("show_rays")
33
+ True
34
+ sage: fan.plot() # needs palp sage.graphs sage.plot sage.symbolic
35
+ Graphics object consisting of 31 graphics primitives
36
+ """
37
+
38
+
39
+ # ****************************************************************************
40
+ # Copyright (C) 2010 Volker Braun <vbraun.name@gmail.com>
41
+ # Copyright (C) 2010 Andrey Novoseltsev <novoselt@gmail.com>
42
+ # Copyright (C) 2010 William Stein <wstein@gmail.com>
43
+ #
44
+ #
45
+ # Distributed under the terms of the GNU General Public License (GPL)
46
+ #
47
+ # https://www.gnu.org/licenses/
48
+ # ****************************************************************************
49
+
50
+ from copy import copy
51
+ from math import pi
52
+
53
+ from sage.arith.misc import integer_ceil as ceil, integer_floor as floor
54
+ from sage.geometry.polyhedron.constructor import Polyhedron
55
+ from sage.misc.lazy_import import lazy_import
56
+ from sage.modules.free_module_element import vector
57
+ lazy_import("sage.plot.all", ["Color", "Graphics",
58
+ "arrow", "disk", "line", "point",
59
+ "polygon", "rainbow", "text"])
60
+ lazy_import("sage.plot.plot3d.all", "text3d")
61
+ from sage.rings.real_double import RDF
62
+ from sage.structure.sage_object import SageObject
63
+
64
+
65
+ # These options are used to initialize/reset plotting options.
66
+ # Most of them are set to "None" and "real default values" are computed
67
+ # automatically based on the plotted object and parameters actually provided by
68
+ # the user.
69
+ _default_options = dict()
70
+ _default_options["mode"] = "round" # Can be also "box" and "generators"
71
+ _default_options["show_lattice"] = None # Default is "True for small plots"
72
+ _default_options["show_rays"] = True
73
+ _default_options["show_generators"] = True
74
+ _default_options["show_walls"] = True
75
+
76
+ _default_options["generator_color"] = "blue"
77
+ _default_options["label_color"] = "black"
78
+ _default_options["point_color"] = "black"
79
+ _default_options["ray_color"] = "purple"
80
+ _default_options["wall_color"] = "rainbow"
81
+ _default_options["wall_alpha"] = 0.4
82
+
83
+ _default_options["point_size"] = None
84
+ _default_options["ray_thickness"] = 3
85
+ _default_options["generator_thickness"] = None
86
+ _default_options["font_size"] = 14
87
+
88
+ _default_options["ray_label"] = "u"
89
+ _default_options["wall_label"] = r"\sigma"
90
+
91
+ # If none of these are given, the default will be 2.5
92
+ _default_options["radius"] = None
93
+ _default_options["xmin"] = None
94
+ _default_options["xmax"] = None
95
+ _default_options["ymin"] = None
96
+ _default_options["ymax"] = None
97
+ _default_options["zmin"] = None
98
+ _default_options["zmax"] = None
99
+
100
+ _default_options["lattice_filter"] = None
101
+
102
+ _default_options["wall_zorder"] = -5
103
+ _default_options["ray_zorder"] = -4
104
+ _default_options["generator_zorder"] = -3
105
+ _default_options["point_zorder"] = -2
106
+ _default_options["label_zorder"] = -1
107
+
108
+ # These options are actually used as "current defaults" in plotting functions.
109
+ _options = copy(_default_options)
110
+
111
+
112
+ class ToricPlotter(SageObject):
113
+ r"""
114
+ Create a toric plotter.
115
+
116
+ INPUT:
117
+
118
+ - ``all_options`` -- a :class:`dictionary <dict>`, containing any of the
119
+ options related to toric objects (see :func:`options`) and any other
120
+ options that will be passed to lower level plotting functions
121
+
122
+ - ``dimension`` -- integer (1, 2, or 3); dimension of toric objects to
123
+ be plotted
124
+
125
+ - ``generators`` -- (optional) a list of ray generators; see examples for
126
+ a detailed explanation of this argument
127
+
128
+ OUTPUT: a toric plotter
129
+
130
+ EXAMPLES:
131
+
132
+ In most cases there is no need to create and use :class:`ToricPlotter`
133
+ directly. Instead, use plotting method of the object which you want to
134
+ plot, e.g. ::
135
+
136
+ sage: fan = toric_varieties.dP6().fan() # needs palp sage.graphs
137
+ sage: fan.plot() # needs palp sage.graphs sage.plot sage.symbolic
138
+ Graphics object consisting of 31 graphics primitives
139
+ sage: print(fan.plot()) # needs palp sage.graphs sage.plot sage.symbolic
140
+ Graphics object consisting of 31 graphics primitives
141
+
142
+ If you do want to create your own plotting function for some toric
143
+ structure, the anticipated usage of toric plotters is the following:
144
+
145
+ - collect all necessary options in a dictionary;
146
+
147
+ - pass these options and ``dimension`` to :class:`ToricPlotter`;
148
+
149
+ - call :meth:`include_points` on ray generators and any other points that
150
+ you want to be present on the plot (it will try to set appropriate
151
+ cut-off bounds);
152
+
153
+ - call :meth:`adjust_options` to choose "nice" default values for all
154
+ options that were not set yet and ensure consistency of rectangular and
155
+ spherical cut-off bounds;
156
+
157
+ - call :meth:`set_rays` on ray generators to scale them to the cut-off
158
+ bounds of the plot;
159
+
160
+ - call appropriate ``plot_*`` functions to actually construct the plot.
161
+
162
+ For example, the plot from the previous example can be obtained as
163
+ follows::
164
+
165
+ sage: # needs palp sage.graphs sage.plot sage.symbolic
166
+ sage: from sage.geometry.toric_plotter import ToricPlotter
167
+ sage: options = dict() # use default for everything
168
+ sage: tp = ToricPlotter(options, fan.lattice().degree())
169
+ sage: tp.include_points(fan.rays())
170
+ sage: tp.adjust_options()
171
+ sage: tp.set_rays(fan.rays())
172
+ sage: result = tp.plot_lattice()
173
+ sage: result += tp.plot_rays()
174
+ sage: result += tp.plot_generators()
175
+ sage: result += tp.plot_walls(fan(2))
176
+ sage: result
177
+ Graphics object consisting of 31 graphics primitives
178
+
179
+ In most situations it is only necessary to include generators of rays, in
180
+ this case they can be passed to the constructor as an optional argument.
181
+ In the example above, the toric plotter can be completely set up using ::
182
+
183
+ sage: tp = ToricPlotter(options, fan.lattice().degree(), fan.rays()) # needs palp sage.graphs sage.plot sage.symbolic
184
+
185
+ All options are exposed as attributes of toric plotters and can be modified
186
+ after constructions, however you will have to manually call
187
+ :meth:`adjust_options` and :meth:`set_rays` again if you decide to change
188
+ the plotting mode and/or cut-off bounds. Otherwise plots maybe invalid.
189
+ """
190
+
191
+ def __init__(self, all_options, dimension, generators=None):
192
+ r"""
193
+ See :class:`ToricPlotter` for documentation.
194
+
195
+ TESTS::
196
+
197
+ sage: from sage.geometry.toric_plotter import ToricPlotter
198
+ sage: tp = ToricPlotter(dict(), 2)
199
+ sage: TestSuite(tp).run()
200
+ """
201
+ super().__init__()
202
+ sd = self.__dict__
203
+ extra_options = dict()
204
+ self.extra_options = extra_options
205
+ toric_options = options()
206
+ for option, value in all_options.items():
207
+ if option in toric_options:
208
+ sd[option] = value
209
+ else:
210
+ extra_options[option] = value
211
+ for option, value in toric_options.items():
212
+ if option not in sd:
213
+ sd[option] = value
214
+ if dimension not in [1, 2, 3]:
215
+ raise ValueError("toric objects can be plotted only for "
216
+ "dimensions 1, 2, and 3, not %s!" % dimension)
217
+ self.dimension = dimension
218
+ self.origin = vector(RDF, max(dimension, 2)) # 1-d is plotted in 2-d
219
+ if self.mode not in ["box", "generators", "round"]:
220
+ raise ValueError("unrecognized plotting mode: %s!" % self.mode)
221
+ # If radius was explicitly set by the user, it sets other bounds too.
222
+ # If we don't take it into account here, they will be replaced by
223
+ # automatically computed values.
224
+ if sd["radius"] is not None:
225
+ for key in ["xmin", "ymin", "zmin"]:
226
+ if sd[key] is None:
227
+ sd[key] = - sd["radius"]
228
+ for key in ["xmax", "ymax", "zmax"]:
229
+ if sd[key] is None:
230
+ sd[key] = sd["radius"]
231
+ # We also set some of the "extra_options" if they were not given.
232
+ if "axes" not in extra_options:
233
+ extra_options["axes"] = False
234
+ if "frame" not in extra_options:
235
+ extra_options["frame"] = False
236
+ if "aspect_ratio" not in extra_options:
237
+ extra_options["aspect_ratio"] = 1
238
+ if generators is not None:
239
+ # Completely prepare the plotter
240
+ self.include_points(generators)
241
+ self.adjust_options()
242
+ self.set_rays(generators)
243
+
244
+ def __eq__(self, other):
245
+ r"""
246
+ Check if ``self`` is equal to ``other``.
247
+
248
+ INPUT:
249
+
250
+ - ``other`` -- anything
251
+
252
+ OUTPUT: ``True`` if ``self`` is equal to ``other``, ``False`` otherwise
253
+
254
+ TESTS::
255
+
256
+ sage: from sage.geometry.toric_plotter import ToricPlotter
257
+ sage: ToricPlotter(dict(), 2) == ToricPlotter(dict(), 2)
258
+ True
259
+ sage: ToricPlotter(dict(), 2) == 0
260
+ False
261
+ """
262
+ # Just to make TestSuite happy...
263
+ return type(self) is type(other) and self.__dict__ == other.__dict__
264
+
265
+ def adjust_options(self):
266
+ r"""
267
+ Adjust plotting options.
268
+
269
+ This function determines appropriate default values for those options,
270
+ that were not specified by the user, based on the other options. See
271
+ :class:`ToricPlotter` for a detailed example.
272
+
273
+ OUTPUT: none
274
+
275
+ TESTS::
276
+
277
+ sage: from sage.geometry.toric_plotter import ToricPlotter
278
+ sage: tp = ToricPlotter(dict(), 2)
279
+ sage: print(tp.show_lattice)
280
+ None
281
+ sage: tp.adjust_options()
282
+ sage: print(tp.show_lattice)
283
+ True
284
+ """
285
+ # Unfortunately, some of the defaults are dimension specific for no
286
+ # good reason but to remedy 2-d/3-d plotting inconsistencies in Sage.
287
+ d = self.dimension
288
+ if d <= 2:
289
+ if self.point_size is None:
290
+ self.point_size = 50
291
+ elif d == 3:
292
+ if self.point_size is None:
293
+ self.point_size = 10
294
+ if self.generator_thickness is None:
295
+ self.generator_thickness = self.ray_thickness
296
+ sd = self.__dict__
297
+ bounds = ["radius", "xmin", "xmax", "ymin", "ymax", "zmin", "zmax"]
298
+ bounds = [abs(sd[bound]) for bound in bounds if sd[bound] is not None]
299
+ r = RDF(max(bounds + [0.5]) if bounds else 2.5)
300
+ self.radius = r
301
+ round = self.mode == "round"
302
+ for key in ["xmin", "ymin", "zmin"]:
303
+ if round or sd[key] is None:
304
+ sd[key] = - r
305
+ sd[key] = min(sd[key], - 0.5)
306
+ sd[key] = RDF(sd[key])
307
+ for key in ["xmax", "ymax", "zmax"]:
308
+ if round or sd[key] is None:
309
+ sd[key] = r
310
+ sd[key] = max(sd[key], 0.5)
311
+ sd[key] = RDF(sd[key])
312
+ if self.show_lattice is None:
313
+ self.show_lattice = (r <= 5) if d <= 2 else r <= 3
314
+
315
+ def include_points(self, points, force=False):
316
+ r"""
317
+ Try to include ``points`` into the bounding box of ``self``.
318
+
319
+ INPUT:
320
+
321
+ - ``points`` -- list of points
322
+
323
+ - ``force`` -- boolean (default: ``False``); by default, only bounds
324
+ that were not set before will be chosen to include ``points``. Use
325
+ ``force=True`` if you don't mind increasing existing bounding box.
326
+
327
+ OUTPUT: none
328
+
329
+ EXAMPLES::
330
+
331
+ sage: from sage.geometry.toric_plotter import ToricPlotter
332
+ sage: tp = ToricPlotter(dict(), 2)
333
+ sage: print(tp.radius)
334
+ None
335
+ sage: tp.include_points([(3, 4)])
336
+ sage: print(tp.radius)
337
+ 5.5...
338
+ sage: tp.include_points([(5, 12)])
339
+ sage: print(tp.radius)
340
+ 5.5...
341
+ sage: tp.include_points([(5, 12)], force=True)
342
+ sage: print(tp.radius)
343
+ 13.5...
344
+ """
345
+ if not points:
346
+ return
347
+ points = [vector(RDF, pt) for pt in points]
348
+ sd = self.__dict__
349
+
350
+ def update(bound, new_value, points):
351
+ if force or sd[bound] is None:
352
+ new_value = eval(new_value)
353
+ if sd[bound] is None:
354
+ sd[bound] = new_value
355
+ elif abs(sd[bound]) < abs(new_value):
356
+ sd[bound] = new_value
357
+
358
+ update("radius", "max(pt.norm() for pt in points) + 0.5", points)
359
+ try:
360
+ update("xmin", "min(pt[0] for pt in points) - 0.5", points)
361
+ update("xmax", "max(pt[0] for pt in points) + 0.5", points)
362
+ update("ymin", "min(pt[1] for pt in points) - 0.5", points)
363
+ update("ymax", "max(pt[1] for pt in points) + 0.5", points)
364
+ update("zmin", "min(pt[2] for pt in points) - 0.5", points)
365
+ update("zmax", "max(pt[2] for pt in points) + 0.5", points)
366
+ except IndexError: # 1 or 2 dimensional case
367
+ pass
368
+
369
+ def plot_generators(self):
370
+ r"""
371
+ Plot ray generators.
372
+
373
+ Ray generators must be specified during construction or using
374
+ :meth:`set_rays` before calling this method.
375
+
376
+ OUTPUT: a plot
377
+
378
+ EXAMPLES::
379
+
380
+ sage: from sage.geometry.toric_plotter import ToricPlotter
381
+ sage: tp = ToricPlotter(dict(), 2, [(3,4)])
382
+ sage: tp.plot_generators() # needs sage.plot
383
+ Graphics object consisting of 1 graphics primitive
384
+ """
385
+ generators = self.generators
386
+ result = Graphics()
387
+ if not generators or not self.show_generators:
388
+ return result
389
+ colors = color_list(self.generator_color, len(generators))
390
+ d = self.dimension
391
+ extra_options = self.extra_options
392
+ origin = self.origin
393
+ thickness = self.generator_thickness
394
+ zorder = self.generator_zorder
395
+ for generator, ray, color in zip(generators, self.rays, colors):
396
+ if ray.dot_product(ray) < generator.dot_product(generator):
397
+ result += line([origin, ray],
398
+ color=color, thickness=thickness,
399
+ zorder=zorder, **extra_options)
400
+ else:
401
+ # This should not be the case, but as of 4.6 plotting
402
+ # functions are inconsistent and arrows behave very
403
+ # different compared to lines.
404
+ if d <= 2:
405
+ result += arrow(origin, generator,
406
+ color=color, width=thickness,
407
+ arrowsize=thickness + 1,
408
+ zorder=zorder, **extra_options)
409
+ else:
410
+ result += line([origin, generator], arrow_head=True,
411
+ color=color, thickness=thickness,
412
+ zorder=zorder, **extra_options)
413
+ return result
414
+
415
+ def plot_labels(self, labels, positions):
416
+ r"""
417
+ Plot ``labels`` at specified ``positions``.
418
+
419
+ INPUT:
420
+
421
+ - ``labels`` -- string or list of strings
422
+
423
+ - ``positions`` -- list of points
424
+
425
+ OUTPUT: a plot
426
+
427
+ EXAMPLES::
428
+
429
+ sage: from sage.geometry.toric_plotter import ToricPlotter
430
+ sage: tp = ToricPlotter(dict(), 2)
431
+ sage: tp.plot_labels("u", [(1.5,0)]) # needs sage.plot
432
+ Graphics object consisting of 1 graphics primitive
433
+ """
434
+ result = Graphics()
435
+ color = self.label_color
436
+ extra_options = self.extra_options
437
+ zorder = self.label_zorder
438
+ font_size = self.font_size
439
+ twod = self.dimension <= 2
440
+ labels = label_list(labels, len(positions), twod)
441
+ for label, position in zip(labels, positions):
442
+ if label is None:
443
+ continue
444
+ if twod:
445
+ result += text(label, position,
446
+ color=color, fontsize=font_size,
447
+ zorder=zorder, **extra_options)
448
+ else:
449
+ result += text3d(label, position, color=color, **extra_options)
450
+ return result
451
+
452
+ def plot_lattice(self):
453
+ r"""
454
+ Plot the lattice (i.e. its points in the cut-off bounds of ``self``).
455
+
456
+ OUTPUT: a plot
457
+
458
+ EXAMPLES::
459
+
460
+ sage: from sage.geometry.toric_plotter import ToricPlotter
461
+ sage: tp = ToricPlotter(dict(), 2)
462
+ sage: tp.adjust_options()
463
+ sage: tp.plot_lattice() # needs sage.plot
464
+ Graphics object consisting of 1 graphics primitive
465
+ """
466
+ if not self.show_lattice:
467
+ # Plot the origin anyway, otherwise rays/generators may look ugly.
468
+ return self.plot_points([self.origin])
469
+ d = self.dimension
470
+ if d == 1:
471
+ points = ((x, 0)
472
+ for x in range(ceil(self.xmin), floor(self.xmax) + 1))
473
+ elif d == 2:
474
+ points = ((x, y)
475
+ for x in range(ceil(self.xmin), floor(self.xmax) + 1)
476
+ for y in range(ceil(self.ymin), floor(self.ymax) + 1))
477
+ elif d == 3:
478
+ points = ((x, y, z)
479
+ for x in range(ceil(self.xmin), floor(self.xmax) + 1)
480
+ for y in range(ceil(self.ymin), floor(self.ymax) + 1)
481
+ for z in range(ceil(self.zmin), floor(self.zmax) + 1))
482
+ if self.mode == "round":
483
+ r = 1.01 * self.radius # To make sure integer values work OK.
484
+ points = (pt for pt in points if vector(pt).dot_product(vector(pt)) <= r)
485
+ f = self.lattice_filter
486
+ if f is not None:
487
+ points = (pt for pt in points if f(pt))
488
+ return self.plot_points(tuple(points))
489
+
490
+ def plot_points(self, points):
491
+ r"""
492
+ Plot given ``points``.
493
+
494
+ INPUT:
495
+
496
+ - ``points`` -- list of points
497
+
498
+ OUTPUT: a plot
499
+
500
+ EXAMPLES::
501
+
502
+ sage: from sage.geometry.toric_plotter import ToricPlotter
503
+ sage: tp = ToricPlotter(dict(), 2)
504
+ sage: tp.adjust_options()
505
+ sage: tp.plot_points([(1,0), (0,1)]) # needs sage.plot
506
+ Graphics object consisting of 1 graphics primitive
507
+ """
508
+ return point(points, color=self.point_color, size=self.point_size,
509
+ zorder=self.point_zorder, **self.extra_options)
510
+
511
+ def plot_ray_labels(self):
512
+ r"""
513
+ Plot ray labels.
514
+
515
+ Usually ray labels are plotted together with rays, but in some cases it
516
+ is desirable to output them separately.
517
+
518
+ Ray generators must be specified during construction or using
519
+ :meth:`set_rays` before calling this method.
520
+
521
+ OUTPUT: a plot
522
+
523
+ EXAMPLES::
524
+
525
+ sage: from sage.geometry.toric_plotter import ToricPlotter
526
+ sage: tp = ToricPlotter(dict(), 2, [(3,4)])
527
+ sage: tp.plot_ray_labels() # needs sage.plot
528
+ Graphics object consisting of 1 graphics primitive
529
+ """
530
+ return self.plot_labels(self.ray_label,
531
+ [1.1 * ray for ray in self.rays])
532
+
533
+ def plot_rays(self):
534
+ r"""
535
+ Plot rays and their labels.
536
+
537
+ Ray generators must be specified during construction or using
538
+ :meth:`set_rays` before calling this method.
539
+
540
+ OUTPUT: a plot
541
+
542
+ EXAMPLES::
543
+
544
+ sage: from sage.geometry.toric_plotter import ToricPlotter
545
+ sage: tp = ToricPlotter(dict(), 2, [(3,4)])
546
+ sage: tp.plot_rays() # needs sage.plot
547
+ Graphics object consisting of 2 graphics primitives
548
+ """
549
+ result = Graphics()
550
+ rays = self.rays
551
+ if not rays or not self.show_rays:
552
+ return result
553
+ extra_options = self.extra_options
554
+ origin = self.origin
555
+ colors = color_list(self.ray_color, len(rays))
556
+ thickness = self.ray_thickness
557
+ zorder = self.ray_zorder
558
+ for end, color in zip(rays, colors):
559
+ result += line([origin, end],
560
+ color=color, thickness=thickness,
561
+ zorder=zorder, **extra_options)
562
+ result += self.plot_ray_labels()
563
+ return result
564
+
565
+ def plot_walls(self, walls):
566
+ r"""
567
+ Plot ``walls``, i.e. 2-d cones, and their labels.
568
+
569
+ Ray generators must be specified during construction or using
570
+ :meth:`set_rays` before calling this method and these specified
571
+ ray generators will be used in conjunction with
572
+ :meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.ambient_ray_indices`
573
+ of ``walls``.
574
+
575
+ INPUT:
576
+
577
+ - ``walls`` -- list of 2-d cones
578
+
579
+ OUTPUT: a plot
580
+
581
+ EXAMPLES::
582
+
583
+ sage: quadrant = Cone([(1,0), (0,1)])
584
+ sage: from sage.geometry.toric_plotter import ToricPlotter
585
+ sage: tp = ToricPlotter(dict(), 2, quadrant.rays())
586
+ sage: tp.plot_walls([quadrant]) # needs sage.plot sage.symbolic
587
+ Graphics object consisting of 2 graphics primitives
588
+
589
+ Let's also check that the truncating polyhedron is functioning
590
+ correctly::
591
+
592
+ sage: tp = ToricPlotter({"mode": "box"}, 2, quadrant.rays())
593
+ sage: tp.plot_walls([quadrant]) # needs sage.plot sage.symbolic
594
+ Graphics object consisting of 2 graphics primitives
595
+ """
596
+ result = Graphics()
597
+ if not walls or not self.show_walls:
598
+ return result
599
+ rays = self.rays
600
+ extra_options = self.extra_options
601
+ mode = self.mode
602
+ alpha = self.wall_alpha
603
+ colors = color_list(self.wall_color, len(walls))
604
+ zorder = self.wall_zorder
605
+ if mode == "box":
606
+ if self.dimension <= 2:
607
+ ieqs = [(self.xmax, -1, 0), (- self.xmin, 1, 0),
608
+ (self.ymax, 0, -1), (- self.ymin, 0, 1)]
609
+ else:
610
+ ieqs = [(self.xmax, -1, 0, 0), (- self.xmin, 1, 0, 0),
611
+ (self.ymax, 0, -1, 0), (- self.ymin, 0, 1, 0),
612
+ (self.zmax, 0, 0, -1), (- self.zmin, 0, 0, 1)]
613
+ box = Polyhedron(ieqs=ieqs, base_ring=RDF)
614
+ for wall, color in zip(walls, colors):
615
+ result += box.intersection(wall.polyhedron()).render_solid(
616
+ alpha=alpha, color=color, zorder=zorder, **extra_options)
617
+ elif mode == "generators":
618
+ origin = self.origin
619
+ for wall, color in zip(walls, colors):
620
+ vertices = [rays[i] for i in wall.ambient_ray_indices()]
621
+ vertices.append(origin)
622
+ result += Polyhedron(vertices=vertices, base_ring=RDF).render_solid(
623
+ alpha=alpha, color=color, zorder=zorder, **extra_options)
624
+ label_sectors = []
625
+ round = mode == "round"
626
+ for wall, color in zip(walls, colors):
627
+ S = wall.linear_subspace()
628
+ lsd = S.dimension()
629
+ if lsd == 0: # Strictly convex wall
630
+ r1, r2 = (rays[i] for i in wall.ambient_ray_indices())
631
+ elif lsd == 1: # wall is a half-plane
632
+ for i, ray in zip(wall.ambient_ray_indices(), wall.rays()):
633
+ if ray in S:
634
+ r1 = rays[i]
635
+ else:
636
+ r2 = rays[i]
637
+ if round:
638
+ # Plot one "extra" sector
639
+ result += sector(- r1, r2,
640
+ alpha=alpha, color=color, zorder=zorder, **extra_options)
641
+ else: # wall is a plane
642
+ r1, r2 = S.basis()
643
+ r1 = vector(RDF, r1)
644
+ r1 = r1 / r1.norm() * self.radius
645
+ r2 = vector(RDF, r2)
646
+ r2 = r2 / r2.norm() * self.radius
647
+ if round:
648
+ # Plot three "extra" sectors
649
+ result += sector(r1, - r2,
650
+ alpha=alpha, color=color, zorder=zorder, **extra_options)
651
+ result += sector(- r1, r2,
652
+ alpha=alpha, color=color, zorder=zorder, **extra_options)
653
+ result += sector(- r1, - r2,
654
+ alpha=alpha, color=color, zorder=zorder, **extra_options)
655
+ label_sectors.append([r1, r2])
656
+ if round:
657
+ result += sector(r1, r2,
658
+ alpha=alpha, color=color, zorder=zorder, **extra_options)
659
+ result += self.plot_labels(self.wall_label,
660
+ [sum(label_sector) / 3 for label_sector in label_sectors])
661
+ return result
662
+
663
+ def set_rays(self, generators):
664
+ r"""
665
+ Set up rays and their ``generators`` to be used by plotting functions.
666
+
667
+ As an alternative to using this method, you can pass ``generators`` to
668
+ :class:`ToricPlotter` constructor.
669
+
670
+ INPUT:
671
+
672
+ - ``generators`` -- list of primitive nonzero ray generators
673
+
674
+ OUTPUT: none
675
+
676
+ EXAMPLES::
677
+
678
+ sage: from sage.geometry.toric_plotter import ToricPlotter
679
+ sage: tp = ToricPlotter(dict(), 2)
680
+ sage: tp.adjust_options()
681
+ sage: tp.plot_rays() # needs sage.plot
682
+ Traceback (most recent call last):
683
+ ...
684
+ AttributeError: 'ToricPlotter' object has no attribute 'rays'...
685
+ sage: tp.set_rays([(0,1)])
686
+ sage: tp.plot_rays() # needs sage.plot
687
+ Graphics object consisting of 2 graphics primitives
688
+ """
689
+ d = self.dimension
690
+ if d == 1:
691
+ generators = [vector(RDF, 2, (gen[0], 0)) for gen in generators]
692
+ else:
693
+ generators = [vector(RDF, d, gen) for gen in generators]
694
+ self.generators = generators
695
+ if self.mode == "box":
696
+ rays = []
697
+ bounds = [self.__dict__[bound]
698
+ for bound in ["xmin", "xmax", "ymin", "ymax", "zmin", "zmax"]]
699
+ bounds = bounds[:2 * d]
700
+ for gen in generators:
701
+ factors = []
702
+ for i, gen_i in enumerate(gen):
703
+ factors.append(gen_i / bounds[2 * i])
704
+ factors.append(gen_i / bounds[2 * i + 1])
705
+ rays.append(gen / max(factors))
706
+ elif self.mode == "generators":
707
+ rays = generators
708
+ elif self.mode == "round":
709
+ r = self.radius
710
+ rays = [r * gen / gen.norm() for gen in generators]
711
+ self.rays = rays
712
+
713
+
714
+ def _unrecognized_option(option):
715
+ r"""
716
+ Raise an exception about wrong ``option``.
717
+
718
+ INPUT:
719
+
720
+ - ``option`` -- string
721
+
722
+ OUTPUT: none, a :exc:`KeyError` exception is raised
723
+
724
+ TESTS::
725
+
726
+ sage: from sage.geometry.toric_plotter import _unrecognized_option
727
+ sage: _unrecognized_option("nontoric")
728
+ Traceback (most recent call last):
729
+ ...
730
+ KeyError: "unrecognized toric plot option: 'nontoric'!
731
+ Type 'toric_plotter.options?' to see available options."
732
+ """
733
+ raise KeyError("unrecognized toric plot option: '%s'! " % option
734
+ + "Type 'toric_plotter.options?' to see available options.")
735
+
736
+
737
+ def color_list(color, n):
738
+ r"""
739
+ Normalize a list of ``n`` colors.
740
+
741
+ INPUT:
742
+
743
+ - ``color`` -- anything specifying a :class:`Color`, a list of such
744
+ specifications, or the string "rainbow";
745
+
746
+ - ``n`` -- integer
747
+
748
+ OUTPUT: list of ``n`` colors
749
+
750
+ If ``color`` specified a single color, it is repeated ``n`` times. If it
751
+ was a list of ``n`` colors, it is returned without changes. If it was
752
+ "rainbow", the rainbow of ``n`` colors is returned.
753
+
754
+ EXAMPLES::
755
+
756
+ sage: # needs sage.plot
757
+ sage: from sage.geometry.toric_plotter import color_list
758
+ sage: color_list("grey", 1)
759
+ [RGB color (0.5019607843137255, 0.5019607843137255, 0.5019607843137255)]
760
+ sage: len(color_list("grey", 3))
761
+ 3
762
+ sage: L = color_list("rainbow", 3)
763
+ sage: L
764
+ [RGB color (1.0, 0.0, 0.0),
765
+ RGB color (0.0, 1.0, 0.0),
766
+ RGB color (0.0, 0.0, 1.0)]
767
+ sage: color_list(L, 3)
768
+ [RGB color (1.0, 0.0, 0.0),
769
+ RGB color (0.0, 1.0, 0.0),
770
+ RGB color (0.0, 0.0, 1.0)]
771
+ sage: color_list(L, 4)
772
+ Traceback (most recent call last):
773
+ ...
774
+ ValueError: expected 4 colors, got 3!
775
+ """
776
+ try:
777
+ color = Color(color)
778
+ return [color] * n
779
+ except (ValueError, TypeError):
780
+ if isinstance(color, (list, tuple)):
781
+ if len(color) != n:
782
+ raise ValueError("expected %d colors, got %d!"
783
+ % (n, len(color)))
784
+ return color
785
+ if color == "rainbow":
786
+ return [Color(c) for c in rainbow(n, "rgbtuple")]
787
+ raise TypeError("cannot interpret %s as a color!" % color)
788
+
789
+
790
+ def label_list(label, n, math_mode, index_set=None):
791
+ r"""
792
+ Normalize a list of ``n`` labels.
793
+
794
+ INPUT:
795
+
796
+ - ``label`` -- ``None``, a string, or a list of string
797
+
798
+ - ``n`` -- integer
799
+
800
+ - ``math_mode`` -- boolean; if ``True``, will produce LaTeX expressions
801
+ for labels
802
+
803
+ - ``index_set`` -- list of integers (default: ``range(n)``) that will be
804
+ used as subscripts for labels
805
+
806
+ OUTPUT: list of ``n`` labels
807
+
808
+ If ``label`` was a list of ``n`` entries, it is returned without changes.
809
+ If ``label`` is ``None``, a list of ``n`` ``None``'s is returned. If
810
+ ``label`` is a string, a list of strings of the form ``$label_{i}$`` is
811
+ returned, where `i` ranges over ``index_set``. (If ``math_mode=False``, the
812
+ form "label_i" is used instead.) If ``n=1``, there is no subscript added,
813
+ unless ``index_set`` was specified explicitly.
814
+
815
+ EXAMPLES::
816
+
817
+ sage: from sage.geometry.toric_plotter import label_list
818
+ sage: label_list("u", 3, False)
819
+ ['u_0', 'u_1', 'u_2']
820
+ sage: label_list("u", 3, True)
821
+ ['$u_{0}$', '$u_{1}$', '$u_{2}$']
822
+ sage: label_list("u", 1, True)
823
+ ['$u$']
824
+ """
825
+ if label is None:
826
+ return [None] * n
827
+ if isinstance(label, (list, tuple)):
828
+ if len(label) != n:
829
+ raise ValueError("expected %d labels, got %d!" % (n, len(label)))
830
+ return label
831
+ if index_set is None:
832
+ if n == 1:
833
+ return ["$%s$" % label.strip("$")] if math_mode else [label]
834
+ index_set = range(n)
835
+ if math_mode:
836
+ label = label.strip("$")
837
+ return list("$%s_{%d}$" % (label, i) for i in index_set)
838
+ else:
839
+ return list("%s_%d" % (label, i) for i in index_set)
840
+
841
+
842
+ def options(option=None, **kwds):
843
+ r"""
844
+ Get or set options for plots of toric geometry objects.
845
+
846
+ .. NOTE::
847
+
848
+ This function provides access to global default options. Any of these
849
+ options can be overridden by passing them directly to plotting
850
+ functions. See also :func:`reset_options`.
851
+
852
+ INPUT:
853
+
854
+ - None;
855
+
856
+ OR:
857
+
858
+ - ``option`` -- string, name of the option whose value you wish to get;
859
+
860
+ OR:
861
+
862
+ - keyword arguments specifying new values for one or more options.
863
+
864
+ OUTPUT:
865
+
866
+ - if there was no input, the dictionary of current options for toric plots;
867
+
868
+ - if ``option`` argument was given, the current value of ``option``;
869
+
870
+ - if other keyword arguments were given, none.
871
+
872
+ **Name Conventions**
873
+
874
+ To clearly distinguish parts of toric plots, in options and methods we use
875
+ the following name conventions:
876
+
877
+ Generator
878
+ A primitive integral vector generating a 1-dimensional cone, plotted as
879
+ an arrow from the origin (or a line, if the head of the arrow is beyond
880
+ cut-off bounds for the plot).
881
+
882
+ Ray
883
+ A 1-dimensional cone, plotted as a line from the origin to the cut-off
884
+ bounds for the plot.
885
+
886
+ Wall
887
+ A 2-dimensional cone, plotted as a region between rays (in the above
888
+ sense). Its exact shape depends on the plotting mode (see below).
889
+
890
+ Chamber
891
+ A 3-dimensional cone, plotting is not implemented yet.
892
+
893
+ **Plotting Modes**
894
+
895
+ A plotting mode mostly determines the shape of the cut-off region (which is
896
+ always relevant for toric plots except for trivial objects consisting of
897
+ the origin only). The following options are available:
898
+
899
+ Box
900
+ The cut-off region is a box with edges parallel to coordinate axes.
901
+
902
+ Generators
903
+ The cut-off region is determined by primitive integral generators of
904
+ rays. Note that this notion is well-defined only for rays and walls,
905
+ in particular you should plot the lattice on your own
906
+ (:meth:`~ToricPlotter.plot_lattice` will use box mode which is likely
907
+ to be unsuitable). While this method may not be suitable for general
908
+ fans, it is quite natural for fans of :class:`CPR-Fano toric varieties.
909
+ <sage.schemes.toric.fano_variety.CPRFanoToricVariety_field`
910
+
911
+ Round
912
+ The cut-off regions is a sphere centered at the origin.
913
+
914
+ **Available Options**
915
+
916
+ Default values for the following options can be set using this function:
917
+
918
+
919
+ - ``mode`` -- "box", "generators", or "round", see above for descriptions;
920
+
921
+ - ``show_lattice`` -- boolean, whether to show lattice points in the
922
+ cut-off region or not;
923
+
924
+ - ``show_rays`` -- boolean, whether to show rays or not;
925
+
926
+ - ``show_generators`` -- boolean, whether to show rays or not;
927
+
928
+ - ``show_walls`` -- boolean, whether to show rays or not;
929
+
930
+ - ``generator_color`` -- a color for generators;
931
+
932
+ - ``label_color`` -- a color for labels;
933
+
934
+ - ``point_color`` -- a color for lattice points;
935
+
936
+ - ``ray_color`` -- a color for rays, a list of colors (one for each ray),
937
+ or the string "rainbow";
938
+
939
+ - ``wall_color`` -- a color for walls, a list of colors (one for each
940
+ wall), or the string "rainbow";
941
+
942
+ - ``wall_alpha`` -- a number between 0 and 1, the alpha-value for walls
943
+ (determining their transparency);
944
+
945
+ - ``point_size`` -- integer; the size of lattice points
946
+
947
+ - ``ray_thickness`` -- integer; the thickness of rays
948
+
949
+ - ``generator_thickness`` -- integer; the thickness of generators
950
+
951
+ - ``font_size`` -- integer; the size of font used for labels
952
+
953
+ - ``ray_label`` -- string or list of strings used for ray labels; use
954
+ ``None`` to hide labels
955
+
956
+ - ``wall_label`` -- string or list of strings used for wall labels; use
957
+ ``None`` to hide labels
958
+
959
+ - ``radius`` -- a positive number, the radius of the cut-off region for
960
+ "round" mode
961
+
962
+ - ``xmin``, ``xmax``, ``ymin``, ``ymax``, ``zmin``, ``zmax`` -- numbers
963
+ determining the cut-off region for "box" mode. Note that you cannot
964
+ exclude the origin - if you try to do so, bounds will be automatically
965
+ expanded to include it.
966
+
967
+ - ``lattice_filter`` -- a callable, taking as an argument a lattice point
968
+ and returning ``True`` if this point should be included on the plot
969
+ (useful, e.g. for plotting sublattices)
970
+
971
+ - ``wall_zorder``, ``ray_zorder``, ``generator_zorder``, ``point_zorder``,
972
+ ``label_zorder`` -- integers, z-orders for different classes of objects.
973
+ By default all values are negative, so that you can add other graphic
974
+ objects on top of a toric plot. You may need to adjust these parameters
975
+ if you want to put a toric plot on top of something else or if you want
976
+ to overlap several toric plots.
977
+
978
+ You can see the current default value of any options by typing, e.g. ::
979
+
980
+ sage: toric_plotter.options("show_rays")
981
+ True
982
+
983
+ If the default value is ``None``, it means that the actual default is
984
+ determined later based on the known options. Note, that not all options can
985
+ be determined in such a way, so you should not set options to ``None``
986
+ unless it was its original state. (You can always revert to this "original
987
+ state" using :meth:`reset_options`.)
988
+
989
+ EXAMPLES:
990
+
991
+ The following line will make all subsequent toric plotting commands to draw
992
+ "rainbows" from walls::
993
+
994
+ sage: toric_plotter.options(wall_color='rainbow')
995
+
996
+ If you prefer a less colorful output (e.g. if you need black-and-white
997
+ illustrations for a paper), you can use something like this::
998
+
999
+ sage: toric_plotter.options(wall_color='grey')
1000
+ """
1001
+ global _options
1002
+ if option is None and not kwds:
1003
+ return copy(_options)
1004
+ elif option is not None and not kwds:
1005
+ try:
1006
+ return _options[option]
1007
+ except KeyError:
1008
+ _unrecognized_option(option)
1009
+ elif option is None and kwds:
1010
+ for option in kwds:
1011
+ try:
1012
+ _options[option] = kwds[option]
1013
+ except KeyError:
1014
+ _unrecognized_option(option)
1015
+ else:
1016
+ raise ValueError("you cannot specify 'option' and other arguments at "
1017
+ "the same time!")
1018
+
1019
+
1020
+ def reset_options():
1021
+ r"""
1022
+ Reset options for plots of toric geometry objects.
1023
+
1024
+ OUTPUT: none
1025
+
1026
+ EXAMPLES::
1027
+
1028
+ sage: toric_plotter.options("show_rays")
1029
+ True
1030
+ sage: toric_plotter.options(show_rays=False)
1031
+ sage: toric_plotter.options("show_rays")
1032
+ False
1033
+
1034
+ Now all toric plots will not show rays, unless explicitly requested. If you
1035
+ want to go back to "default defaults", use this method::
1036
+
1037
+ sage: toric_plotter.reset_options()
1038
+ sage: toric_plotter.options("show_rays")
1039
+ True
1040
+ """
1041
+ global _options
1042
+ _options = copy(_default_options)
1043
+
1044
+
1045
+ def sector(ray1, ray2, **extra_options):
1046
+ r"""
1047
+ Plot a sector between ``ray1`` and ``ray2`` centered at the origin.
1048
+
1049
+ .. NOTE::
1050
+
1051
+ This function was intended for plotting strictly convex cones, so it
1052
+ plots the smaller sector between ``ray1`` and ``ray2`` and, therefore,
1053
+ they cannot be opposite. If you do want to use this function for bigger
1054
+ regions, split them into several parts.
1055
+
1056
+ .. NOTE::
1057
+
1058
+ As of version 4.6 Sage does not have a graphic primitive for sectors in
1059
+ 3-dimensional space, so this function will actually approximate them
1060
+ using polygons (the number of vertices used depends on the angle
1061
+ between rays).
1062
+
1063
+ INPUT:
1064
+
1065
+ - ``ray1``, ``ray2`` -- rays in 2- or 3-dimensional space of the same
1066
+ length
1067
+
1068
+ - ``extra_options`` -- dictionary of options that should be passed to
1069
+ lower level plotting functions
1070
+
1071
+ OUTPUT: a plot
1072
+
1073
+ EXAMPLES::
1074
+
1075
+ sage: from sage.geometry.toric_plotter import sector
1076
+ sage: sector((1,0), (0,1)) # needs sage.symbolic
1077
+ Graphics object consisting of 1 graphics primitive
1078
+ sage: sector((3,2,1), (1,2,3)) # needs sage.plot
1079
+ Graphics3d Object
1080
+ """
1081
+ from sage.functions.all import arccos, arctan2
1082
+
1083
+ ray1 = vector(RDF, ray1)
1084
+ ray2 = vector(RDF, ray2)
1085
+ r = ray1.norm()
1086
+ if len(ray1) == 2:
1087
+ # Plot an honest sector
1088
+ phi1 = arctan2(ray1[1], ray1[0])
1089
+ phi2 = arctan2(ray2[1], ray2[0])
1090
+ if phi1 > phi2:
1091
+ phi1, phi2 = phi2, phi1
1092
+ if phi2 - phi1 > pi:
1093
+ phi1, phi2 = phi2, phi1 + 2 * pi
1094
+ return disk((0,0), r, (phi1, phi2), **extra_options)
1095
+ else:
1096
+ # Plot a polygon, 30 vertices per radian.
1097
+ vertices_per_radian = 30
1098
+ n = ceil(arccos(ray1 * ray2 / r**2) * vertices_per_radian)
1099
+ dr = (ray2 - ray1) / n
1100
+ points = (ray1 + i * dr for i in range(n + 1))
1101
+ points = [r / pt.norm() * pt for pt in points]
1102
+ points.append(vector(RDF, 3))
1103
+ return polygon(points, **extra_options)