passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_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.
Files changed (719) hide show
  1. passagemath_categories-10.6.32.dist-info/METADATA +156 -0
  2. passagemath_categories-10.6.32.dist-info/RECORD +719 -0
  3. passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
  4. passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
  5. passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  7. passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  8. sage/all__sagemath_categories.py +28 -0
  9. sage/arith/all.py +38 -0
  10. sage/arith/constants.pxd +27 -0
  11. sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
  12. sage/arith/functions.pxd +4 -0
  13. sage/arith/functions.pyx +221 -0
  14. sage/arith/misc.py +6552 -0
  15. sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
  16. sage/arith/multi_modular.pxd +39 -0
  17. sage/arith/multi_modular.pyx +994 -0
  18. sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
  19. sage/arith/rational_reconstruction.pxd +4 -0
  20. sage/arith/rational_reconstruction.pyx +115 -0
  21. sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
  22. sage/arith/srange.pyx +571 -0
  23. sage/calculus/all__sagemath_categories.py +2 -0
  24. sage/calculus/functional.py +481 -0
  25. sage/calculus/functions.py +151 -0
  26. sage/categories/additive_groups.py +73 -0
  27. sage/categories/additive_magmas.py +1044 -0
  28. sage/categories/additive_monoids.py +114 -0
  29. sage/categories/additive_semigroups.py +184 -0
  30. sage/categories/affine_weyl_groups.py +238 -0
  31. sage/categories/algebra_ideals.py +95 -0
  32. sage/categories/algebra_modules.py +96 -0
  33. sage/categories/algebras.py +349 -0
  34. sage/categories/algebras_with_basis.py +377 -0
  35. sage/categories/all.py +160 -0
  36. sage/categories/aperiodic_semigroups.py +29 -0
  37. sage/categories/associative_algebras.py +47 -0
  38. sage/categories/bialgebras.py +101 -0
  39. sage/categories/bialgebras_with_basis.py +414 -0
  40. sage/categories/bimodules.py +206 -0
  41. sage/categories/chain_complexes.py +268 -0
  42. sage/categories/classical_crystals.py +480 -0
  43. sage/categories/coalgebras.py +405 -0
  44. sage/categories/coalgebras_with_basis.py +232 -0
  45. sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
  46. sage/categories/coercion_methods.pyx +52 -0
  47. sage/categories/commutative_additive_groups.py +104 -0
  48. sage/categories/commutative_additive_monoids.py +45 -0
  49. sage/categories/commutative_additive_semigroups.py +48 -0
  50. sage/categories/commutative_algebra_ideals.py +87 -0
  51. sage/categories/commutative_algebras.py +94 -0
  52. sage/categories/commutative_ring_ideals.py +58 -0
  53. sage/categories/commutative_rings.py +736 -0
  54. sage/categories/complete_discrete_valuation.py +293 -0
  55. sage/categories/complex_reflection_groups.py +145 -0
  56. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  57. sage/categories/coxeter_group_algebras.py +186 -0
  58. sage/categories/coxeter_groups.py +3402 -0
  59. sage/categories/crystals.py +2628 -0
  60. sage/categories/cw_complexes.py +216 -0
  61. sage/categories/dedekind_domains.py +137 -0
  62. sage/categories/discrete_valuation.py +325 -0
  63. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  64. sage/categories/division_rings.py +114 -0
  65. sage/categories/domains.py +95 -0
  66. sage/categories/drinfeld_modules.py +789 -0
  67. sage/categories/dual.py +42 -0
  68. sage/categories/enumerated_sets.py +1146 -0
  69. sage/categories/euclidean_domains.py +271 -0
  70. sage/categories/examples/algebras_with_basis.py +102 -0
  71. sage/categories/examples/all.py +1 -0
  72. sage/categories/examples/commutative_additive_monoids.py +130 -0
  73. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  74. sage/categories/examples/coxeter_groups.py +8 -0
  75. sage/categories/examples/crystals.py +236 -0
  76. sage/categories/examples/cw_complexes.py +163 -0
  77. sage/categories/examples/facade_sets.py +187 -0
  78. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  79. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  80. sage/categories/examples/finite_coxeter_groups.py +252 -0
  81. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  82. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  83. sage/categories/examples/finite_enumerated_sets.py +208 -0
  84. sage/categories/examples/finite_monoids.py +150 -0
  85. sage/categories/examples/finite_semigroups.py +190 -0
  86. sage/categories/examples/finite_weyl_groups.py +191 -0
  87. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  88. sage/categories/examples/graded_modules_with_basis.py +168 -0
  89. sage/categories/examples/graphs.py +122 -0
  90. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  91. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  92. sage/categories/examples/lie_algebras.py +352 -0
  93. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  94. sage/categories/examples/magmas.py +162 -0
  95. sage/categories/examples/manifolds.py +94 -0
  96. sage/categories/examples/monoids.py +144 -0
  97. sage/categories/examples/posets.py +178 -0
  98. sage/categories/examples/semigroups.py +580 -0
  99. sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  100. sage/categories/examples/semigroups_cython.pyx +221 -0
  101. sage/categories/examples/semirings.py +249 -0
  102. sage/categories/examples/sets_cat.py +706 -0
  103. sage/categories/examples/sets_with_grading.py +101 -0
  104. sage/categories/examples/with_realizations.py +542 -0
  105. sage/categories/fields.py +991 -0
  106. sage/categories/filtered_algebras.py +63 -0
  107. sage/categories/filtered_algebras_with_basis.py +548 -0
  108. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  109. sage/categories/filtered_modules.py +210 -0
  110. sage/categories/filtered_modules_with_basis.py +1209 -0
  111. sage/categories/finite_complex_reflection_groups.py +1506 -0
  112. sage/categories/finite_coxeter_groups.py +1138 -0
  113. sage/categories/finite_crystals.py +103 -0
  114. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  115. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  116. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  118. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  119. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  120. sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
  121. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  122. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  123. sage/categories/finite_enumerated_sets.py +769 -0
  124. sage/categories/finite_fields.py +252 -0
  125. sage/categories/finite_groups.py +256 -0
  126. sage/categories/finite_lattice_posets.py +242 -0
  127. sage/categories/finite_monoids.py +316 -0
  128. sage/categories/finite_permutation_groups.py +339 -0
  129. sage/categories/finite_posets.py +1994 -0
  130. sage/categories/finite_semigroups.py +136 -0
  131. sage/categories/finite_sets.py +93 -0
  132. sage/categories/finite_weyl_groups.py +39 -0
  133. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  134. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  135. sage/categories/finitely_generated_magmas.py +57 -0
  136. sage/categories/finitely_generated_semigroups.py +214 -0
  137. sage/categories/function_fields.py +76 -0
  138. sage/categories/g_sets.py +77 -0
  139. sage/categories/gcd_domains.py +65 -0
  140. sage/categories/generalized_coxeter_groups.py +94 -0
  141. sage/categories/graded_algebras.py +85 -0
  142. sage/categories/graded_algebras_with_basis.py +258 -0
  143. sage/categories/graded_bialgebras.py +32 -0
  144. sage/categories/graded_bialgebras_with_basis.py +32 -0
  145. sage/categories/graded_coalgebras.py +65 -0
  146. sage/categories/graded_coalgebras_with_basis.py +51 -0
  147. sage/categories/graded_hopf_algebras.py +41 -0
  148. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  149. sage/categories/graded_lie_algebras.py +91 -0
  150. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  151. sage/categories/graded_lie_conformal_algebras.py +74 -0
  152. sage/categories/graded_modules.py +133 -0
  153. sage/categories/graded_modules_with_basis.py +329 -0
  154. sage/categories/graphs.py +138 -0
  155. sage/categories/group_algebras.py +430 -0
  156. sage/categories/groupoid.py +94 -0
  157. sage/categories/groups.py +667 -0
  158. sage/categories/h_trivial_semigroups.py +64 -0
  159. sage/categories/hecke_modules.py +185 -0
  160. sage/categories/highest_weight_crystals.py +980 -0
  161. sage/categories/hopf_algebras.py +219 -0
  162. sage/categories/hopf_algebras_with_basis.py +309 -0
  163. sage/categories/infinite_enumerated_sets.py +115 -0
  164. sage/categories/integral_domains.py +203 -0
  165. sage/categories/j_trivial_semigroups.py +29 -0
  166. sage/categories/kac_moody_algebras.py +82 -0
  167. sage/categories/kahler_algebras.py +203 -0
  168. sage/categories/l_trivial_semigroups.py +63 -0
  169. sage/categories/lambda_bracket_algebras.py +280 -0
  170. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  171. sage/categories/lattice_posets.py +89 -0
  172. sage/categories/left_modules.py +49 -0
  173. sage/categories/lie_algebras.py +1070 -0
  174. sage/categories/lie_algebras_with_basis.py +261 -0
  175. sage/categories/lie_conformal_algebras.py +350 -0
  176. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  177. sage/categories/lie_groups.py +73 -0
  178. sage/categories/loop_crystals.py +1290 -0
  179. sage/categories/magmas.py +1189 -0
  180. sage/categories/magmas_and_additive_magmas.py +149 -0
  181. sage/categories/magmatic_algebras.py +365 -0
  182. sage/categories/manifolds.py +352 -0
  183. sage/categories/matrix_algebras.py +40 -0
  184. sage/categories/metric_spaces.py +387 -0
  185. sage/categories/modular_abelian_varieties.py +78 -0
  186. sage/categories/modules.py +989 -0
  187. sage/categories/modules_with_basis.py +2794 -0
  188. sage/categories/monoid_algebras.py +38 -0
  189. sage/categories/monoids.py +739 -0
  190. sage/categories/noetherian_rings.py +87 -0
  191. sage/categories/number_fields.py +242 -0
  192. sage/categories/ore_modules.py +189 -0
  193. sage/categories/partially_ordered_monoids.py +49 -0
  194. sage/categories/permutation_groups.py +63 -0
  195. sage/categories/pointed_sets.py +42 -0
  196. sage/categories/polyhedra.py +74 -0
  197. sage/categories/poor_man_map.py +270 -0
  198. sage/categories/posets.py +722 -0
  199. sage/categories/principal_ideal_domains.py +270 -0
  200. sage/categories/quantum_group_representations.py +543 -0
  201. sage/categories/quotient_fields.py +728 -0
  202. sage/categories/r_trivial_semigroups.py +45 -0
  203. sage/categories/regular_crystals.py +898 -0
  204. sage/categories/regular_supercrystals.py +170 -0
  205. sage/categories/right_modules.py +49 -0
  206. sage/categories/ring_ideals.py +74 -0
  207. sage/categories/rings.py +1904 -0
  208. sage/categories/rngs.py +175 -0
  209. sage/categories/schemes.py +393 -0
  210. sage/categories/semigroups.py +1060 -0
  211. sage/categories/semirings.py +71 -0
  212. sage/categories/semisimple_algebras.py +114 -0
  213. sage/categories/sets_with_grading.py +235 -0
  214. sage/categories/shephard_groups.py +43 -0
  215. sage/categories/signed_tensor.py +120 -0
  216. sage/categories/simplicial_complexes.py +134 -0
  217. sage/categories/simplicial_sets.py +1206 -0
  218. sage/categories/super_algebras.py +149 -0
  219. sage/categories/super_algebras_with_basis.py +144 -0
  220. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  221. sage/categories/super_lie_conformal_algebras.py +193 -0
  222. sage/categories/super_modules.py +229 -0
  223. sage/categories/super_modules_with_basis.py +193 -0
  224. sage/categories/supercommutative_algebras.py +99 -0
  225. sage/categories/supercrystals.py +406 -0
  226. sage/categories/tensor.py +110 -0
  227. sage/categories/topological_spaces.py +170 -0
  228. sage/categories/triangular_kac_moody_algebras.py +439 -0
  229. sage/categories/tutorial.py +58 -0
  230. sage/categories/unique_factorization_domains.py +318 -0
  231. sage/categories/unital_algebras.py +426 -0
  232. sage/categories/vector_bundles.py +159 -0
  233. sage/categories/vector_spaces.py +357 -0
  234. sage/categories/weyl_groups.py +853 -0
  235. sage/combinat/all__sagemath_categories.py +34 -0
  236. sage/combinat/backtrack.py +180 -0
  237. sage/combinat/combinat.py +2269 -0
  238. sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  239. sage/combinat/combinat_cython.pxd +6 -0
  240. sage/combinat/combinat_cython.pyx +390 -0
  241. sage/combinat/combination.py +796 -0
  242. sage/combinat/combinatorial_map.py +416 -0
  243. sage/combinat/composition.py +2192 -0
  244. sage/combinat/dlx.py +510 -0
  245. sage/combinat/integer_lists/__init__.py +7 -0
  246. sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
  247. sage/combinat/integer_lists/base.pxd +16 -0
  248. sage/combinat/integer_lists/base.pyx +713 -0
  249. sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
  250. sage/combinat/integer_lists/invlex.pxd +4 -0
  251. sage/combinat/integer_lists/invlex.pyx +1650 -0
  252. sage/combinat/integer_lists/lists.py +328 -0
  253. sage/combinat/integer_lists/nn.py +48 -0
  254. sage/combinat/integer_vector.py +1818 -0
  255. sage/combinat/integer_vector_weighted.py +413 -0
  256. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  257. sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
  258. sage/combinat/matrices/dancing_links.pyx +1159 -0
  259. sage/combinat/matrices/dancing_links_c.h +380 -0
  260. sage/combinat/matrices/dlxcpp.py +136 -0
  261. sage/combinat/partition.py +10070 -0
  262. sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
  263. sage/combinat/partitions.pyx +743 -0
  264. sage/combinat/permutation.py +10168 -0
  265. sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  266. sage/combinat/permutation_cython.pxd +11 -0
  267. sage/combinat/permutation_cython.pyx +407 -0
  268. sage/combinat/q_analogues.py +1090 -0
  269. sage/combinat/ranker.py +268 -0
  270. sage/combinat/subset.py +1561 -0
  271. sage/combinat/subsets_hereditary.py +202 -0
  272. sage/combinat/subsets_pairwise.py +184 -0
  273. sage/combinat/tools.py +63 -0
  274. sage/combinat/tuple.py +348 -0
  275. sage/data_structures/all.py +2 -0
  276. sage/data_structures/all__sagemath_categories.py +2 -0
  277. sage/data_structures/binary_matrix.pxd +138 -0
  278. sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
  279. sage/data_structures/binary_search.pxd +3 -0
  280. sage/data_structures/binary_search.pyx +66 -0
  281. sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
  282. sage/data_structures/bitset.pxd +40 -0
  283. sage/data_structures/bitset.pyx +2385 -0
  284. sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
  285. sage/data_structures/bitset_base.pxd +926 -0
  286. sage/data_structures/bitset_base.pyx +117 -0
  287. sage/data_structures/bitset_intrinsics.h +487 -0
  288. sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  289. sage/data_structures/blas_dict.pxd +12 -0
  290. sage/data_structures/blas_dict.pyx +469 -0
  291. sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
  292. sage/data_structures/list_of_pairs.pxd +16 -0
  293. sage/data_structures/list_of_pairs.pyx +122 -0
  294. sage/data_structures/mutable_poset.py +3312 -0
  295. sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
  296. sage/data_structures/pairing_heap.h +346 -0
  297. sage/data_structures/pairing_heap.pxd +88 -0
  298. sage/data_structures/pairing_heap.pyx +1464 -0
  299. sage/data_structures/sparse_bitset.pxd +62 -0
  300. sage/data_structures/stream.py +5070 -0
  301. sage/databases/all__sagemath_categories.py +7 -0
  302. sage/databases/sql_db.py +2236 -0
  303. sage/ext/all__sagemath_categories.py +3 -0
  304. sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
  305. sage/ext/fast_callable.pxd +4 -0
  306. sage/ext/fast_callable.pyx +2746 -0
  307. sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
  308. sage/ext/fast_eval.pxd +1 -0
  309. sage/ext/fast_eval.pyx +102 -0
  310. sage/ext/interpreters/__init__.py +1 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
  313. sage/ext/interpreters/wrapper_el.pxd +18 -0
  314. sage/ext/interpreters/wrapper_el.pyx +148 -0
  315. sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
  316. sage/ext/interpreters/wrapper_py.pxd +17 -0
  317. sage/ext/interpreters/wrapper_py.pyx +133 -0
  318. sage/functions/airy.py +937 -0
  319. sage/functions/all.py +97 -0
  320. sage/functions/bessel.py +2102 -0
  321. sage/functions/error.py +784 -0
  322. sage/functions/exp_integral.py +1529 -0
  323. sage/functions/gamma.py +1087 -0
  324. sage/functions/generalized.py +672 -0
  325. sage/functions/hyperbolic.py +747 -0
  326. sage/functions/hypergeometric.py +1156 -0
  327. sage/functions/jacobi.py +1705 -0
  328. sage/functions/log.py +1402 -0
  329. sage/functions/min_max.py +338 -0
  330. sage/functions/orthogonal_polys.py +3106 -0
  331. sage/functions/other.py +2303 -0
  332. sage/functions/piecewise.py +1505 -0
  333. sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
  334. sage/functions/prime_pi.pyx +262 -0
  335. sage/functions/special.py +1212 -0
  336. sage/functions/spike_function.py +278 -0
  337. sage/functions/transcendental.py +690 -0
  338. sage/functions/trig.py +1062 -0
  339. sage/functions/wigner.py +726 -0
  340. sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  341. sage/geometry/abc.pyx +82 -0
  342. sage/geometry/all__sagemath_categories.py +1 -0
  343. sage/groups/all__sagemath_categories.py +11 -0
  344. sage/groups/generic.py +1733 -0
  345. sage/groups/groups_catalog.py +113 -0
  346. sage/groups/perm_gps/all__sagemath_categories.py +1 -0
  347. sage/groups/perm_gps/partn_ref/all.py +1 -0
  348. sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
  349. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
  350. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
  351. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
  352. sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
  353. sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
  354. sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
  355. sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
  356. sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
  357. sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
  358. sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
  359. sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
  360. sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
  361. sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
  362. sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
  363. sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
  364. sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
  365. sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
  366. sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
  367. sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
  368. sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
  369. sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
  370. sage/interfaces/abc.py +140 -0
  371. sage/interfaces/all.py +58 -0
  372. sage/interfaces/all__sagemath_categories.py +1 -0
  373. sage/interfaces/expect.py +1643 -0
  374. sage/interfaces/interface.py +1682 -0
  375. sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +288 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
  381. sage/interfaces/sagespawn.pyx +308 -0
  382. sage/interfaces/tab_completion.py +101 -0
  383. sage/misc/all__sagemath_categories.py +78 -0
  384. sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
  393. sage/misc/citation.pyx +159 -0
  394. sage/misc/converting_dict.py +293 -0
  395. sage/misc/defaults.py +129 -0
  396. sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
  397. sage/misc/derivative.pyx +223 -0
  398. sage/misc/functional.py +2005 -0
  399. sage/misc/html.py +589 -0
  400. sage/misc/latex.py +2673 -0
  401. sage/misc/latex_macros.py +236 -0
  402. sage/misc/latex_standalone.py +1833 -0
  403. sage/misc/map_threaded.py +38 -0
  404. sage/misc/mathml.py +76 -0
  405. sage/misc/method_decorator.py +88 -0
  406. sage/misc/mrange.py +755 -0
  407. sage/misc/multireplace.py +41 -0
  408. sage/misc/object_multiplexer.py +92 -0
  409. sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
  410. sage/misc/parser.pyx +1107 -0
  411. sage/misc/random_testing.py +264 -0
  412. sage/misc/rest_index_of_methods.py +377 -0
  413. sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
  417. sage/misc/stopgap.pyx +95 -0
  418. sage/misc/table.py +853 -0
  419. sage/monoids/all__sagemath_categories.py +1 -0
  420. sage/monoids/indexed_free_monoid.py +1071 -0
  421. sage/monoids/monoid.py +82 -0
  422. sage/numerical/all__sagemath_categories.py +1 -0
  423. sage/numerical/backends/all__sagemath_categories.py +1 -0
  424. sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  425. sage/numerical/backends/generic_backend.pxd +61 -0
  426. sage/numerical/backends/generic_backend.pyx +1893 -0
  427. sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  428. sage/numerical/backends/generic_sdp_backend.pxd +38 -0
  429. sage/numerical/backends/generic_sdp_backend.pyx +755 -0
  430. sage/parallel/all.py +6 -0
  431. sage/parallel/decorate.py +575 -0
  432. sage/parallel/map_reduce.py +1997 -0
  433. sage/parallel/multiprocessing_sage.py +76 -0
  434. sage/parallel/ncpus.py +35 -0
  435. sage/parallel/parallelism.py +364 -0
  436. sage/parallel/reference.py +47 -0
  437. sage/parallel/use_fork.py +333 -0
  438. sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  439. sage/rings/abc.pxd +31 -0
  440. sage/rings/abc.pyx +526 -0
  441. sage/rings/algebraic_closure_finite_field.py +1154 -0
  442. sage/rings/all__sagemath_categories.py +91 -0
  443. sage/rings/big_oh.py +227 -0
  444. sage/rings/continued_fraction.py +2754 -0
  445. sage/rings/continued_fraction_gosper.py +220 -0
  446. sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
  449. sage/rings/fast_arith.pxd +21 -0
  450. sage/rings/fast_arith.pyx +535 -0
  451. sage/rings/finite_rings/all__sagemath_categories.py +9 -0
  452. sage/rings/finite_rings/conway_polynomials.py +542 -0
  453. sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  454. sage/rings/finite_rings/element_base.pxd +12 -0
  455. sage/rings/finite_rings/element_base.pyx +1176 -0
  456. sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  457. sage/rings/finite_rings/finite_field_base.pxd +7 -0
  458. sage/rings/finite_rings/finite_field_base.pyx +2171 -0
  459. sage/rings/finite_rings/finite_field_constructor.py +827 -0
  460. sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
  461. sage/rings/finite_rings/galois_group.py +154 -0
  462. sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  463. sage/rings/finite_rings/hom_finite_field.pxd +23 -0
  464. sage/rings/finite_rings/hom_finite_field.pyx +856 -0
  465. sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  466. sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
  467. sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
  468. sage/rings/finite_rings/homset.py +357 -0
  469. sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
  470. sage/rings/finite_rings/integer_mod.pxd +56 -0
  471. sage/rings/finite_rings/integer_mod.pyx +4586 -0
  472. sage/rings/finite_rings/integer_mod_limits.h +11 -0
  473. sage/rings/finite_rings/integer_mod_ring.py +2044 -0
  474. sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
  475. sage/rings/finite_rings/residue_field.pxd +30 -0
  476. sage/rings/finite_rings/residue_field.pyx +1811 -0
  477. sage/rings/finite_rings/stdint.pxd +19 -0
  478. sage/rings/fraction_field.py +1452 -0
  479. sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
  480. sage/rings/fraction_field_element.pyx +1357 -0
  481. sage/rings/function_field/all.py +7 -0
  482. sage/rings/function_field/all__sagemath_categories.py +2 -0
  483. sage/rings/function_field/constructor.py +218 -0
  484. sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
  485. sage/rings/function_field/element.pxd +11 -0
  486. sage/rings/function_field/element.pyx +1008 -0
  487. sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
  488. sage/rings/function_field/element_rational.pyx +513 -0
  489. sage/rings/function_field/extensions.py +230 -0
  490. sage/rings/function_field/function_field.py +1468 -0
  491. sage/rings/function_field/function_field_rational.py +1005 -0
  492. sage/rings/function_field/ideal.py +1155 -0
  493. sage/rings/function_field/ideal_rational.py +629 -0
  494. sage/rings/function_field/jacobian_base.py +826 -0
  495. sage/rings/function_field/jacobian_hess.py +1053 -0
  496. sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
  497. sage/rings/function_field/maps.py +1039 -0
  498. sage/rings/function_field/order.py +281 -0
  499. sage/rings/function_field/order_basis.py +586 -0
  500. sage/rings/function_field/order_rational.py +576 -0
  501. sage/rings/function_field/place.py +426 -0
  502. sage/rings/function_field/place_rational.py +181 -0
  503. sage/rings/generic.py +320 -0
  504. sage/rings/homset.py +332 -0
  505. sage/rings/ideal.py +1885 -0
  506. sage/rings/ideal_monoid.py +215 -0
  507. sage/rings/infinity.py +1890 -0
  508. sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
  512. sage/rings/integer_ring.pxd +8 -0
  513. sage/rings/integer_ring.pyx +1693 -0
  514. sage/rings/laurent_series_ring.py +931 -0
  515. sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  516. sage/rings/laurent_series_ring_element.pxd +11 -0
  517. sage/rings/laurent_series_ring_element.pyx +1927 -0
  518. sage/rings/lazy_series.py +7815 -0
  519. sage/rings/lazy_series_ring.py +4356 -0
  520. sage/rings/localization.py +1043 -0
  521. sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
  522. sage/rings/morphism.pxd +39 -0
  523. sage/rings/morphism.pyx +3299 -0
  524. sage/rings/multi_power_series_ring.py +1145 -0
  525. sage/rings/multi_power_series_ring_element.py +2184 -0
  526. sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
  527. sage/rings/noncommutative_ideals.pyx +423 -0
  528. sage/rings/number_field/all__sagemath_categories.py +1 -0
  529. sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  530. sage/rings/number_field/number_field_base.pxd +8 -0
  531. sage/rings/number_field/number_field_base.pyx +507 -0
  532. sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  533. sage/rings/number_field/number_field_element_base.pxd +6 -0
  534. sage/rings/number_field/number_field_element_base.pyx +36 -0
  535. sage/rings/number_field/number_field_ideal.py +3550 -0
  536. sage/rings/padics/all__sagemath_categories.py +4 -0
  537. sage/rings/padics/local_generic.py +1670 -0
  538. sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
  539. sage/rings/padics/local_generic_element.pxd +5 -0
  540. sage/rings/padics/local_generic_element.pyx +1017 -0
  541. sage/rings/padics/misc.py +256 -0
  542. sage/rings/padics/padic_generic.py +1911 -0
  543. sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
  544. sage/rings/padics/pow_computer.pxd +38 -0
  545. sage/rings/padics/pow_computer.pyx +671 -0
  546. sage/rings/padics/precision_error.py +24 -0
  547. sage/rings/polynomial/all__sagemath_categories.py +25 -0
  548. sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  549. sage/rings/polynomial/commutative_polynomial.pxd +6 -0
  550. sage/rings/polynomial/commutative_polynomial.pyx +24 -0
  551. sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
  552. sage/rings/polynomial/cyclotomic.pyx +404 -0
  553. sage/rings/polynomial/flatten.py +711 -0
  554. sage/rings/polynomial/ideal.py +102 -0
  555. sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
  556. sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
  557. sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  558. sage/rings/polynomial/laurent_polynomial.pxd +18 -0
  559. sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
  560. sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
  561. sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
  562. sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
  563. sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +12 -0
  565. sage/rings/polynomial/multi_polynomial.pyx +3082 -0
  566. sage/rings/polynomial/multi_polynomial_element.py +2570 -0
  567. sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
  568. sage/rings/polynomial/multi_polynomial_ring.py +947 -0
  569. sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
  570. sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
  571. sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
  572. sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
  573. sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
  577. sage/rings/polynomial/polynomial_compiled.pxd +59 -0
  578. sage/rings/polynomial/polynomial_compiled.pyx +509 -0
  579. sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +64 -0
  581. sage/rings/polynomial/polynomial_element.pyx +13255 -0
  582. sage/rings/polynomial/polynomial_element_generic.py +1637 -0
  583. sage/rings/polynomial/polynomial_fateman.py +97 -0
  584. sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
  585. sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
  586. sage/rings/polynomial/polynomial_ring.py +3784 -0
  587. sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
  588. sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
  589. sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
  590. sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
  591. sage/rings/polynomial/polynomial_singular_interface.py +549 -0
  592. sage/rings/polynomial/symmetric_ideal.py +989 -0
  593. sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
  594. sage/rings/polynomial/symmetric_reduction.pxd +8 -0
  595. sage/rings/polynomial/symmetric_reduction.pyx +669 -0
  596. sage/rings/polynomial/term_order.py +2279 -0
  597. sage/rings/polynomial/toy_buchberger.py +449 -0
  598. sage/rings/polynomial/toy_d_basis.py +387 -0
  599. sage/rings/polynomial/toy_variety.py +362 -0
  600. sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
  601. sage/rings/power_series_mpoly.pxd +9 -0
  602. sage/rings/power_series_mpoly.pyx +161 -0
  603. sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
  604. sage/rings/power_series_poly.pxd +10 -0
  605. sage/rings/power_series_poly.pyx +1317 -0
  606. sage/rings/power_series_ring.py +1441 -0
  607. sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  608. sage/rings/power_series_ring_element.pxd +12 -0
  609. sage/rings/power_series_ring_element.pyx +3028 -0
  610. sage/rings/puiseux_series_ring.py +487 -0
  611. sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  612. sage/rings/puiseux_series_ring_element.pxd +7 -0
  613. sage/rings/puiseux_series_ring_element.pyx +1055 -0
  614. sage/rings/qqbar_decorators.py +167 -0
  615. sage/rings/quotient_ring.py +1598 -0
  616. sage/rings/quotient_ring_element.py +979 -0
  617. sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
  618. sage/rings/rational.pxd +20 -0
  619. sage/rings/rational.pyx +4284 -0
  620. sage/rings/rational_field.py +1730 -0
  621. sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  628. sage/rings/ring.pxd +30 -0
  629. sage/rings/ring.pyx +850 -0
  630. sage/rings/semirings/all.py +3 -0
  631. sage/rings/semirings/non_negative_integer_semiring.py +107 -0
  632. sage/rings/semirings/tropical_mpolynomial.py +972 -0
  633. sage/rings/semirings/tropical_polynomial.py +997 -0
  634. sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
  635. sage/rings/semirings/tropical_semiring.pyx +676 -0
  636. sage/rings/semirings/tropical_variety.py +1701 -0
  637. sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
  638. sage/rings/sum_of_squares.pxd +3 -0
  639. sage/rings/sum_of_squares.pyx +336 -0
  640. sage/rings/tests.py +504 -0
  641. sage/schemes/affine/affine_homset.py +508 -0
  642. sage/schemes/affine/affine_morphism.py +1574 -0
  643. sage/schemes/affine/affine_point.py +460 -0
  644. sage/schemes/affine/affine_rational_point.py +308 -0
  645. sage/schemes/affine/affine_space.py +1264 -0
  646. sage/schemes/affine/affine_subscheme.py +592 -0
  647. sage/schemes/affine/all.py +25 -0
  648. sage/schemes/all__sagemath_categories.py +5 -0
  649. sage/schemes/generic/algebraic_scheme.py +2092 -0
  650. sage/schemes/generic/all.py +5 -0
  651. sage/schemes/generic/ambient_space.py +400 -0
  652. sage/schemes/generic/divisor.py +465 -0
  653. sage/schemes/generic/divisor_group.py +313 -0
  654. sage/schemes/generic/glue.py +84 -0
  655. sage/schemes/generic/homset.py +820 -0
  656. sage/schemes/generic/hypersurface.py +234 -0
  657. sage/schemes/generic/morphism.py +2107 -0
  658. sage/schemes/generic/point.py +237 -0
  659. sage/schemes/generic/scheme.py +1190 -0
  660. sage/schemes/generic/spec.py +199 -0
  661. sage/schemes/product_projective/all.py +6 -0
  662. sage/schemes/product_projective/homset.py +236 -0
  663. sage/schemes/product_projective/morphism.py +517 -0
  664. sage/schemes/product_projective/point.py +568 -0
  665. sage/schemes/product_projective/rational_point.py +550 -0
  666. sage/schemes/product_projective/space.py +1301 -0
  667. sage/schemes/product_projective/subscheme.py +466 -0
  668. sage/schemes/projective/all.py +24 -0
  669. sage/schemes/projective/proj_bdd_height.py +453 -0
  670. sage/schemes/projective/projective_homset.py +718 -0
  671. sage/schemes/projective/projective_morphism.py +2792 -0
  672. sage/schemes/projective/projective_point.py +1484 -0
  673. sage/schemes/projective/projective_rational_point.py +569 -0
  674. sage/schemes/projective/projective_space.py +2571 -0
  675. sage/schemes/projective/projective_subscheme.py +1574 -0
  676. sage/sets/all.py +17 -0
  677. sage/sets/cartesian_product.py +376 -0
  678. sage/sets/condition_set.py +525 -0
  679. sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
  680. sage/sets/disjoint_set.pxd +36 -0
  681. sage/sets/disjoint_set.pyx +998 -0
  682. sage/sets/disjoint_union_enumerated_sets.py +625 -0
  683. sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
  684. sage/sets/family.pxd +12 -0
  685. sage/sets/family.pyx +1556 -0
  686. sage/sets/finite_enumerated_set.py +406 -0
  687. sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
  688. sage/sets/finite_set_map_cy.pxd +34 -0
  689. sage/sets/finite_set_map_cy.pyx +708 -0
  690. sage/sets/finite_set_maps.py +591 -0
  691. sage/sets/image_set.py +448 -0
  692. sage/sets/integer_range.py +829 -0
  693. sage/sets/non_negative_integers.py +241 -0
  694. sage/sets/positive_integers.py +93 -0
  695. sage/sets/primes.py +188 -0
  696. sage/sets/real_set.py +2760 -0
  697. sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2082 -0
  700. sage/sets/set.py +2083 -0
  701. sage/sets/set_from_iterator.py +1021 -0
  702. sage/sets/totally_ordered_finite_set.py +329 -0
  703. sage/symbolic/all__sagemath_categories.py +1 -0
  704. sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
  705. sage/symbolic/function.pxd +29 -0
  706. sage/symbolic/function.pyx +1488 -0
  707. sage/symbolic/symbols.py +56 -0
  708. sage/tests/all__sagemath_categories.py +1 -0
  709. sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
  712. sage/tests/stl_vector.pyx +171 -0
  713. sage/typeset/all.py +6 -0
  714. sage/typeset/ascii_art.py +295 -0
  715. sage/typeset/character_art.py +789 -0
  716. sage/typeset/character_art_factory.py +572 -0
  717. sage/typeset/symbols.py +334 -0
  718. sage/typeset/unicode_art.py +183 -0
  719. sage/typeset/unicode_characters.py +101 -0
@@ -0,0 +1,1833 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ r"""
3
+ Standalone LaTeX Document class and TikzPicture
4
+
5
+ This module contains two Python classes. Firstly, it contains a class
6
+ :class:`Standalone` to represent a LaTeX file using the standalone__
7
+ document class.
8
+
9
+ __ http://www.ctan.org/pkg/standalone
10
+
11
+ From its documentation:
12
+
13
+ *The standalone bundle allows users to easily place picture environments
14
+ or other material in own source files and compile these on their own or as
15
+ part of a main document. A special standalone class is provided for use
16
+ with such files, which by default crops the resulting output file to the
17
+ content. The standalone package enables the user to simply load the
18
+ standalone files using ``\input`` inside a main document.*
19
+
20
+ Secondly, it contains a class :class:`TikzPicture` which inherits from
21
+ :class:`Standalone` that represents a LaTeX file using the standalone
22
+ document class and containing a tikzpicture.
23
+
24
+ A Python Module for PGF/Tikz pictures. A TikzPicture object is created from
25
+ a string starting with ``r'\begin{tikzpicture}'`` and ending with
26
+ ``r'\end{tikzpicture}'``.
27
+
28
+ The module allows to convert a standalone LaTeX document class file,
29
+ including tikzpictures, to an image. It allows conversion to pdf, png and
30
+ svg formats. It also show them automatically in Jupyter using rich
31
+ representation.
32
+
33
+ According to wikipedia, `PGF/TikZ`__ is a pair of languages for producing
34
+ vector graphics (e.g., technical illustrations and drawings) from a
35
+ geometric/algebraic description, with standard features including the
36
+ drawing of points, lines, arrows, paths, circles, ellipses and polygons.
37
+
38
+ __ https://www.ctan.org/pkg/pgf
39
+
40
+ EXAMPLES:
41
+
42
+ Standalone LaTeX document class
43
+ -------------------------------
44
+
45
+ First *Hello World* example::
46
+
47
+ sage: from sage.misc.latex_standalone import Standalone
48
+ sage: Standalone('Hello World')
49
+ \documentclass{standalone}
50
+ \begin{document}
51
+ Hello World
52
+ \end{document}
53
+
54
+ Loading a few latex packages::
55
+
56
+ sage: Standalone('Hello World', usepackage=['amsmath', 'amsfont'])
57
+ \documentclass{standalone}
58
+ \usepackage{amsmath}
59
+ \usepackage{amsfont}
60
+ \begin{document}
61
+ Hello World
62
+ \end{document}
63
+
64
+ Setting few standalone options (see documentation of standalone for a
65
+ complete list)::
66
+
67
+ sage: Standalone('Hello World', standalone_config=["border=4mm", "beamer=true"])
68
+ \documentclass{standalone}
69
+ \standaloneconfig{border=4mm}
70
+ \standaloneconfig{beamer=true}
71
+ \begin{document}
72
+ Hello World
73
+ \end{document}
74
+
75
+ Adding your own list of macros::
76
+
77
+ sage: Standalone('Hello World', macros=[r'\newcommand{\ZZ}{\mathbb{Z}}'])
78
+ \documentclass{standalone}
79
+ \newcommand{\ZZ}{\mathbb{Z}}
80
+ \begin{document}
81
+ Hello World
82
+ \end{document}
83
+
84
+ It provides conversion to images of different format::
85
+
86
+ sage: from sage.misc.latex_standalone import Standalone
87
+ sage: s = Standalone('Hello World')
88
+ sage: _ = s.pdf() # not tested
89
+ sage: _ = s.png() # not tested
90
+ sage: _ = s.svg() # not tested
91
+ sage: s # not tested, in Jupyter, this shows the image directly below the cell
92
+
93
+ TikzPicture
94
+ -----------
95
+
96
+ This module also contains a class :class:`TikzPicture` which inherits from
97
+ :class:`Standalone` to represent more specifically a tikzpicture which is
98
+ within a standalone document class.
99
+
100
+ First construct a string describing a tikzpicture::
101
+
102
+ sage: lines = []
103
+ sage: lines.append(r'\begin{tikzpicture}')
104
+ sage: lines.append(r'\draw[very thick,orange,->] (0,0) -- (1,1);')
105
+ sage: lines.append(r'\end{tikzpicture}')
106
+ sage: s = '\n'.join(lines)
107
+ sage: print(s)
108
+ \begin{tikzpicture}
109
+ \draw[very thick,orange,->] (0,0) -- (1,1);
110
+ \end{tikzpicture}
111
+
112
+ One may provide it as input to ``TikzPicture``::
113
+
114
+ sage: from sage.misc.latex_standalone import TikzPicture
115
+ sage: t = TikzPicture(s)
116
+
117
+ In the terminal, the following shows the content of the standalone
118
+ document class tex file which contains the tikzpicture. In Jupyter, it
119
+ shows the picture itself::
120
+
121
+ sage: t
122
+ \documentclass[tikz]{standalone}
123
+ \begin{document}
124
+ \begin{tikzpicture}
125
+ \draw[very thick,orange,->] (0,0) -- (1,1);
126
+ \end{tikzpicture}
127
+ \end{document}
128
+
129
+ As it is the case for :class:`Standalone`, the constructor of
130
+ ``TikzPicture`` has many arguments allowing for example to add some more
131
+ ``\usepackage`` lines::
132
+
133
+ sage: t = TikzPicture(s, usepackage=['amsmath'])
134
+ sage: t
135
+ \documentclass[tikz]{standalone}
136
+ \usepackage{amsmath}
137
+ \begin{document}
138
+ \begin{tikzpicture}
139
+ \draw[very thick,orange,->] (0,0) -- (1,1);
140
+ \end{tikzpicture}
141
+ \end{document}
142
+
143
+ Moreover, it allows to load some tikz libraries::
144
+
145
+ sage: t = TikzPicture(s, usetikzlibrary=['arrows'])
146
+ sage: t
147
+ \documentclass[tikz]{standalone}
148
+ \usetikzlibrary{arrows}
149
+ \begin{document}
150
+ \begin{tikzpicture}
151
+ \draw[very thick,orange,->] (0,0) -- (1,1);
152
+ \end{tikzpicture}
153
+ \end{document}
154
+
155
+ The following example illustrates that it works when providing the
156
+ tikzpicture code generated by Sage from some polyhedron::
157
+
158
+ sage: from sage.misc.latex_standalone import TikzPicture
159
+ sage: V = [[1,0,1], [1,0,0], [1,1,0], [0,0,-1],
160
+ ....: [0,1,0], [-1,0,0], [0,1,1], [0,0,1], [0,-1,0]]
161
+ sage: P = Polyhedron(vertices=V).polar() # needs sage.geometry.polyhedron
162
+ sage: s1 = P.projection().tikz([674,108,-731],112, output_type='LatexExpr') # needs sage.geometry.polyhedron sage.plot
163
+ sage: t1 = TikzPicture(s1) # needs sage.geometry.polyhedron sage.plot
164
+
165
+ Open the image in a viewer (the returned value is a string giving the
166
+ absolute path to the file in some temporary directory)::
167
+
168
+ sage: path_to_file = t1.pdf() # not tested # needs sage.geometry.polyhedron sage.plot
169
+
170
+ Instead, you may save a pdf of the tikzpicture into a file of your choice
171
+ (but this does not open the viewer)::
172
+
173
+ sage: _ = t1.pdf('tikz_polytope.pdf') # not tested # needs sage.geometry.polyhedron sage.plot
174
+
175
+ Opening the image in a viewer can be turned off::
176
+
177
+ sage: _ = t1.pdf(view=False) # long time (2s), optional - latex, needs sage.geometry.polyhedron sage.plot
178
+
179
+ The same can be done with png format (translated from pdf with convert
180
+ command which needs the installation of imagemagick)::
181
+
182
+ sage: _ = t1.png(view=False) # long time (2s), optional - imagemagick latex, needs sage.geometry.polyhedron sage.plot
183
+
184
+ The string representation gives the header (5 lines) and tail (5 lines) of
185
+ the tikzpicture. In Jupyter, it will instead use rich representation and
186
+ show the image directly below the cell in png or svg format::
187
+
188
+ sage: t1 # needs sage.geometry.polyhedron sage.plot
189
+ \documentclass[tikz]{standalone}
190
+ \begin{document}
191
+ \begin{tikzpicture}%
192
+ [x={(0.249656cm, -0.577639cm)},
193
+ y={(0.777700cm, -0.358578cm)},
194
+ z={(-0.576936cm, -0.733318cm)},
195
+ ...
196
+ \node[vertex] at (0.00000, -1.00000, 0.00000) {};
197
+ \node[vertex] at (-0.50000, -0.50000, -0.50000) {};
198
+ %%
199
+ %%
200
+ \end{tikzpicture}
201
+ \end{document}
202
+
203
+ Use ``print(t)`` to see the complete content of the file::
204
+
205
+ sage: print(t1) # not tested # needs sage.geometry.polyhedron sage.plot
206
+
207
+ Adding a border in the options avoids cropping the vertices of a graph::
208
+
209
+ sage: # needs sage.graphs
210
+ sage: g = graphs.PetersenGraph()
211
+ sage: s2 = latex(g) # takes 3s but the result is cached # optional - latex
212
+ sage: t2 = TikzPicture(s2, standalone_config=["border=4mm"], # optional - latex
213
+ ....: usepackage=['tkz-graph'])
214
+ sage: _ = t2.pdf() # not tested
215
+
216
+ The current latex representation of a transducer is a tikzpicture using
217
+ the tikz library automata. The string can be used as input::
218
+
219
+ sage: # needs sage.graphs sage.modules
220
+ sage: s3 = latex(transducers.GrayCode())
221
+ sage: t3 = TikzPicture(s3, usetikzlibrary=['automata'])
222
+ sage: _ = t3.pdf(view=False) # long time (2s) # optional - latex
223
+
224
+ AUTHORS:
225
+
226
+ - Sébastien Labbé, initial version in slabbe-0.2.spkg, nov 2015.
227
+ - Sébastien Labbé, inclusion into SageMath from slabbe-0.6.2, July 2021.
228
+ """
229
+
230
+ # ****************************************************************************
231
+ # Copyright (C) 2015-2022 Sébastien Labbé <slabqc@gmail.com>
232
+ #
233
+ # Distributed under the terms of the GNU General Public License (GPL)
234
+ # as published by the Free Software Foundation; either version 2 of
235
+ # the License, or (at your option) any later version.
236
+ # https://www.gnu.org/licenses/
237
+ # ****************************************************************************
238
+ from subprocess import run
239
+ import os
240
+
241
+ from sage.structure.sage_object import SageObject
242
+ from sage.misc.superseded import experimental
243
+
244
+
245
+ class Standalone(SageObject):
246
+ r"""
247
+ LaTeX standalone document class.
248
+
249
+ INPUT:
250
+
251
+ - ``content`` -- string; the content to be added in the document
252
+ between lines ``r'\begin{document}'`` and ``r'\end{document}'``
253
+ - ``document_class_options`` -- list of strings (default: ``[]``);
254
+ latex document class standalone options. Such options appear on the
255
+ line ``\documentclass[...]{standalone}`` between the brackets.
256
+ - ``standalone_config`` -- list of strings (default: ``[]``);
257
+ standalone configuration options. Such options are defined with
258
+ ``\standaloneconfig{...}``.
259
+ - ``usepackage`` -- list of strings (default: ``[]``); latex packages
260
+ - ``macros`` -- list of strings (default: ``[]``); stuff you need for the picture
261
+ - ``use_sage_preamble`` -- boolean (default: ``False``); whether to include sage
262
+ latex preamble and sage latex macros, that is, the content of
263
+ :func:`sage.misc.latex.extra_preamble()`,
264
+ :func:`sage.misc.latex.extra_macros()` and
265
+ :func:`sage.misc.latex_macros.sage_latex_macros()`
266
+
267
+ EXAMPLES::
268
+
269
+ sage: from sage.misc.latex_standalone import Standalone
270
+ sage: content = "\\section{Intro}\nTest\n"
271
+ sage: t = Standalone(content)
272
+ sage: t
273
+ \documentclass{standalone}
274
+ \begin{document}
275
+ \section{Intro}
276
+ Test
277
+ \end{document}
278
+
279
+ ::
280
+
281
+ sage: t = Standalone(content, standalone_config=["border=4mm"],
282
+ ....: usepackage=['amsmath'])
283
+ sage: t
284
+ \documentclass{standalone}
285
+ \standaloneconfig{border=4mm}
286
+ \usepackage{amsmath}
287
+ \begin{document}
288
+ \section{Intro}
289
+ Test
290
+ \end{document}
291
+ """
292
+ def __init__(self, content, document_class_options=None,
293
+ standalone_config=None, usepackage=None, macros=None,
294
+ use_sage_preamble=False):
295
+ r"""
296
+ See :class:`Standalone` for full information.
297
+
298
+ EXAMPLES::
299
+
300
+ sage: from sage.misc.latex_standalone import Standalone
301
+ sage: content = "\\section{Intro}\n\nTest\n"
302
+ sage: t = Standalone(content)
303
+ """
304
+ self._content = content
305
+ self._document_class_options = [] if document_class_options is None else list(document_class_options)
306
+ self._standalone_config = [] if standalone_config is None else standalone_config
307
+ self._usepackage = [] if usepackage is None else usepackage
308
+ self._macros = [] if macros is None else macros
309
+ if use_sage_preamble:
310
+ from sage.misc.latex import _Latex_prefs
311
+ for key in ['preamble', 'macros']:
312
+ s = _Latex_prefs._option[key]
313
+ if s:
314
+ self._macros.append(s)
315
+ from sage.misc.latex_macros import sage_latex_macros
316
+ self._macros.extend(sage_latex_macros())
317
+
318
+ def _latex_file_header_lines(self):
319
+ r"""
320
+ EXAMPLES::
321
+
322
+ sage: latex.extra_preamble('')
323
+ sage: from sage.misc.latex_standalone import Standalone
324
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
325
+ sage: A = ['tikz']
326
+ sage: B = ["border=4mm"]
327
+ sage: C = ['amsmath']
328
+ sage: t = Standalone(s, document_class_options=A, standalone_config=B, usepackage=C)
329
+ sage: t._latex_file_header_lines()[:6]
330
+ ['\\documentclass[tikz]{standalone}',
331
+ '\\standaloneconfig{border=4mm}',
332
+ '\\usepackage{amsmath}']
333
+ """
334
+ lines = []
335
+ if self._document_class_options:
336
+ options = ','.join(self._document_class_options)
337
+ lines.append(r"\documentclass[{}]{{standalone}}".format(options))
338
+ else:
339
+ lines.append(r"\documentclass{standalone}")
340
+ lines.extend(r"\standaloneconfig{{{}}}".format(config)
341
+ for config in self._standalone_config)
342
+ lines.extend(r"\usepackage{{{}}}".format(package)
343
+ for package in self._usepackage)
344
+ lines.extend(self._macros)
345
+ return lines
346
+
347
+ def _repr_(self):
348
+ r"""
349
+ Return a string representation of the Standalone file.
350
+
351
+ It contains the first few and last few lines of the content.
352
+
353
+ .. NOTE::
354
+
355
+ Use ``print(t)`` or ``str(t)`` to show or get the full content.
356
+
357
+ EXAMPLES:
358
+
359
+ When the content has 10 lines or less, it shows it all::
360
+
361
+ sage: from sage.misc.latex_standalone import Standalone
362
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
363
+ sage: t = Standalone(s, document_class_options=['tikz'], standalone_config=["border=4mm"], usepackage=['amsmath'])
364
+ sage: t
365
+ \documentclass[tikz]{standalone}
366
+ \standaloneconfig{border=4mm}
367
+ \usepackage{amsmath}
368
+ \begin{document}
369
+ \begin{tikzpicture}
370
+ \draw (0,0) -- (1,1);
371
+ \end{tikzpicture}
372
+ \end{document}
373
+
374
+ When the content more than 10 lines, it shows the head (first 5
375
+ lines) and tail (last 5 lines) of the content together with the
376
+ complete header of the standalone latex document. The number of
377
+ missing lines and the number of characters in the content is
378
+ written allowing to detect a change if needed::
379
+
380
+ sage: lines = []
381
+ sage: lines.append(r'\begin{tikzpicture}')
382
+ sage: lines.append(r'\draw[->] (-.5,0) -- (20,0);')
383
+ sage: lines.extend(r'\draw({i},-.5) -- ({i},.5);'.format(i=i) for i in range(20))
384
+ sage: lines.append(r'\end{tikzpicture}')
385
+ sage: t = Standalone('\n'.join(lines), document_class_options=['tikz'])
386
+ sage: t
387
+ \documentclass[tikz]{standalone}
388
+ \begin{document}
389
+ \begin{tikzpicture}
390
+ \draw[->] (-.5,0) -- (20,0);
391
+ \draw(0,-.5) -- (0,.5);
392
+ \draw(1,-.5) -- (1,.5);
393
+ \draw(2,-.5) -- (2,.5);
394
+ ---
395
+ 13 lines not printed (566 characters in total).
396
+ Use print to see the full content.
397
+ ---
398
+ \draw(16,-.5) -- (16,.5);
399
+ \draw(17,-.5) -- (17,.5);
400
+ \draw(18,-.5) -- (18,.5);
401
+ \draw(19,-.5) -- (19,.5);
402
+ \end{tikzpicture}
403
+ \end{document}
404
+ """
405
+ lines = self._latex_file_header_lines()
406
+ lines.append(r"\begin{document}")
407
+ L = self._content.splitlines()
408
+ if len(L) <= 10:
409
+ lines.extend(L)
410
+ else:
411
+ lines.extend(L[:5])
412
+ lines.append('---')
413
+ lines.append('{} lines not printed ({} characters in total).'.format(len(L) - 10,
414
+ len(self._content)))
415
+ lines.append('Use print to see the full content.')
416
+ lines.append('---')
417
+ lines.extend(L[-5:])
418
+ lines.append(r"\end{document}")
419
+ return '\n'.join(lines)
420
+
421
+ def _rich_repr_(self, display_manager, **kwds):
422
+ r"""
423
+ Rich Output Magic Method.
424
+
425
+ See :mod:`sage.repl.rich_output` for details.
426
+
427
+ EXAMPLES::
428
+
429
+ sage: from sage.repl.rich_output import get_display_manager
430
+ sage: dm = get_display_manager()
431
+ sage: dm.is_in_terminal()
432
+ False
433
+
434
+ sage: from sage.misc.latex_standalone import TikzPicture
435
+ sage: lines = []
436
+ sage: lines.append(r'\begin{tikzpicture}')
437
+ sage: lines.append(r'\draw[very thick,orange,->] (0,0) -- (1,1);')
438
+ sage: lines.append(r'\end{tikzpicture}')
439
+ sage: s = '\n'.join(lines)
440
+ sage: t = TikzPicture(s)
441
+ sage: t._rich_repr_(dm) # random result is Text in doctest
442
+ OutputImagePng container
443
+
444
+ Using vector svg instead of png::
445
+
446
+ sage: dm.preferences.graphics = 'vector'
447
+ sage: t._rich_repr_(dm) # random result is Text in doctest
448
+ OutputImageSvg container
449
+ sage: dm.preferences.graphics = 'raster'
450
+ """
451
+ # Do not use rich output in the terminal
452
+ if display_manager.is_in_terminal():
453
+ return
454
+ # Do not use rich output if not in IPython notebook (Jupyter)
455
+ from sage.repl.rich_output.backend_ipython import BackendIPythonNotebook
456
+ if not isinstance(display_manager._backend, BackendIPythonNotebook):
457
+ return
458
+
459
+ types = display_manager.types
460
+ prefer_raster = (
461
+ ('png', types.OutputImagePng),
462
+ )
463
+ prefer_vector = (
464
+ ('svg', types.OutputImageSvg),
465
+ ('pdf', types.OutputImagePdf),
466
+ )
467
+ graphics = display_manager.preferences.graphics
468
+ if graphics == 'disable':
469
+ return
470
+ elif graphics == 'raster' or graphics is None:
471
+ preferred = prefer_raster + prefer_vector
472
+ elif graphics == 'vector':
473
+ preferred = prefer_vector + prefer_raster
474
+ else:
475
+ raise ValueError('unknown graphics output preference')
476
+
477
+ for format, output_container in preferred:
478
+ if output_container in display_manager.supported_output():
479
+ filename = getattr(self, format)(view=False, **kwds)
480
+ from sage.repl.rich_output.buffer import OutputBuffer
481
+ buf = OutputBuffer.from_file(filename)
482
+ return output_container(buf)
483
+
484
+ def __str__(self):
485
+ r"""
486
+ Return the complete string of the standalone document class file.
487
+
488
+ EXAMPLES::
489
+
490
+ sage: from sage.misc.latex_standalone import Standalone
491
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
492
+ sage: t = Standalone(s, document_class_options=['tikz'])
493
+ sage: print(t)
494
+ \RequirePackage{luatex85}
495
+ \documentclass[tikz]{standalone}
496
+ \begin{document}
497
+ \begin{tikzpicture}
498
+ \draw (0,0) -- (1,1);
499
+ \end{tikzpicture}
500
+ \end{document}
501
+ """
502
+ lines = []
503
+ # LuaLaTeX, TeXLive 2016, standalone: undefined control sequence
504
+ # https://tex.stackexchange.com/questions/315025
505
+ # fixed in 2018, meanwhile, we add the fix here
506
+ lines.append(r"\RequirePackage{luatex85}")
507
+ lines.extend(self._latex_file_header_lines())
508
+ lines.append(r"\begin{document}")
509
+ lines.append(self._content)
510
+ lines.append(r"\end{document}")
511
+ return '\n'.join(lines)
512
+
513
+ def content(self):
514
+ r"""
515
+ Return the content of the standalone document class file.
516
+
517
+ EXAMPLES::
518
+
519
+ sage: from sage.misc.latex_standalone import Standalone
520
+ sage: t = Standalone('Hello World')
521
+ sage: t.content()
522
+ 'Hello World'
523
+
524
+ ::
525
+
526
+ sage: from sage.misc.latex_standalone import TikzPicture
527
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
528
+ sage: t = TikzPicture(s)
529
+ sage: print(t.content())
530
+ \begin{tikzpicture}
531
+ \draw (0,0) -- (1,1);
532
+ \end{tikzpicture}
533
+ """
534
+ return self._content
535
+
536
+ def add_document_class_option(self, option):
537
+ r"""
538
+ Add a document class option.
539
+
540
+ INPUT:
541
+
542
+ - ``option`` -- string
543
+
544
+ EXAMPLES::
545
+
546
+ sage: from sage.misc.latex_standalone import Standalone
547
+ sage: t = Standalone('Hello World')
548
+ sage: t.add_document_class_option('beamer')
549
+ sage: t
550
+ \documentclass[beamer]{standalone}
551
+ \begin{document}
552
+ Hello World
553
+ \end{document}
554
+ """
555
+ self._document_class_options.append(option)
556
+
557
+ def add_standalone_config(self, config):
558
+ r"""
559
+ Add a standalone config.
560
+
561
+ INPUT:
562
+
563
+ - ``config`` -- string
564
+
565
+ EXAMPLES::
566
+
567
+ sage: from sage.misc.latex_standalone import Standalone
568
+ sage: t = Standalone('Hello World')
569
+ sage: t.add_standalone_config("border=4mm")
570
+ sage: t
571
+ \documentclass{standalone}
572
+ \standaloneconfig{border=4mm}
573
+ \begin{document}
574
+ Hello World
575
+ \end{document}
576
+ """
577
+ self._standalone_config.append(config)
578
+
579
+ def add_usepackage(self, package):
580
+ r"""
581
+ Add a ``usepackage`` line.
582
+
583
+ INPUT:
584
+
585
+ - ``package`` -- string, name of package
586
+
587
+ EXAMPLES::
588
+
589
+ sage: from sage.misc.latex_standalone import Standalone
590
+ sage: t = Standalone('Hello World')
591
+ sage: t.add_usepackage('amsmath')
592
+ sage: t
593
+ \documentclass{standalone}
594
+ \usepackage{amsmath}
595
+ \begin{document}
596
+ Hello World
597
+ \end{document}
598
+ """
599
+ self._usepackage.append(package)
600
+
601
+ def add_macro(self, macro):
602
+ r"""
603
+ Add a macro.
604
+
605
+ INPUT:
606
+
607
+ - ``macro`` -- string, newcommand line
608
+
609
+ EXAMPLES::
610
+
611
+ sage: from sage.misc.latex_standalone import Standalone
612
+ sage: t = Standalone('Hello World')
613
+ sage: t.add_macro(r'\newcommand{\ZZ}{\mathbb{Z}}')
614
+ sage: t
615
+ \documentclass{standalone}
616
+ \newcommand{\ZZ}{\mathbb{Z}}
617
+ \begin{document}
618
+ Hello World
619
+ \end{document}
620
+ """
621
+ self._macros.append(macro)
622
+
623
+ def pdf(self, filename=None, view=True, program=None):
624
+ r"""
625
+ Compile the latex code with pdflatex and create a pdf file.
626
+
627
+ INPUT:
628
+
629
+ - ``filename`` -- string (default: ``None``); the output filename.
630
+ If ``None``, it saves the file in a temporary directory.
631
+
632
+ - ``view`` -- boolean (default: ``True``); whether to open the file in a
633
+ pdf viewer. This option is ignored and automatically set to
634
+ ``False`` if ``filename`` is not ``None``.
635
+
636
+ - ``program`` -- string (default: ``None``); ``'pdflatex'`` or
637
+ ``'lualatex'``. If ``None``, it uses ``'lualatex'`` if it is
638
+ available, otherwise ``'pdflatex'``.
639
+
640
+ OUTPUT: string, path to pdf file
641
+
642
+ EXAMPLES::
643
+
644
+ sage: from sage.misc.latex_standalone import Standalone
645
+ sage: t = Standalone('Hello World')
646
+ sage: _ = t.pdf(view=False) # long time (1s) # optional - latex
647
+
648
+ Same for instances of :class:`TikzPicture`::
649
+
650
+ sage: from sage.misc.latex_standalone import TikzPicture
651
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
652
+ sage: t = TikzPicture(s)
653
+ sage: _ = t.pdf(view=False) # not tested
654
+
655
+ A filename may be provided where to save the file, in which case
656
+ the viewer does not open the file::
657
+
658
+ sage: from sage.misc.temporary_file import tmp_filename
659
+ sage: filename = tmp_filename('temp','.pdf')
660
+ sage: path_to_file = t.pdf(filename) # long time (1s) # optional - latex
661
+ sage: path_to_file[-4:] # long time (fast) # optional - latex
662
+ '.pdf'
663
+
664
+ The filename may contain spaces::
665
+
666
+ sage: filename = tmp_filename('filename with spaces','.pdf')
667
+ sage: path_to_file = t.pdf(filename) # long time (1s) # optional - latex
668
+
669
+ TESTS:
670
+
671
+ We test the behavior when a wrong tex string is provided::
672
+
673
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
674
+ sage: s_missing_last_character = s[:-1]
675
+ sage: t = TikzPicture(s_missing_last_character)
676
+ sage: _ = t.pdf() # optional - latex
677
+ Traceback (most recent call last):
678
+ ...
679
+ CalledProcessError: Command '['...latex', '-interaction=nonstopmode',
680
+ 'tikz_...tex']' returned non-zero exit status 1.
681
+ """
682
+ from sage.features.latex import lualatex, pdflatex
683
+
684
+ # Set default program
685
+ if program is None:
686
+ if lualatex().is_present():
687
+ program = 'lualatex'
688
+ else:
689
+ program = 'pdflatex'
690
+
691
+ # Check availability of programs
692
+ if program == 'pdflatex':
693
+ pdflatex().require()
694
+ elif program == 'lualatex':
695
+ lualatex().require()
696
+ else:
697
+ raise ValueError("program(={}) should be pdflatex or lualatex".format(program))
698
+
699
+ # set up filenames
700
+ from sage.misc.temporary_file import tmp_filename
701
+ temp_filename_tex = tmp_filename('tikz_', '.tex')
702
+ with open(temp_filename_tex, 'w') as f:
703
+ f.write(str(self))
704
+ base, temp_filename_tex = os.path.split(temp_filename_tex)
705
+ temp_filename, ext = os.path.splitext(temp_filename_tex)
706
+
707
+ # running pdflatex or lualatex
708
+ cmd = [program, '-interaction=nonstopmode', temp_filename_tex]
709
+ result = run(cmd, cwd=base, capture_output=True, text=True)
710
+
711
+ # If a problem with the tex source occurs, provide the log
712
+ if result.returncode != 0:
713
+ print("Command \n"
714
+ " '{}'\n"
715
+ "returned nonzero exit status {}.\n"
716
+ "Here is the content of the stderr:{}\n"
717
+ "Here is the content of the stdout:"
718
+ "{}\n".format(' '.join(result.args),
719
+ result.returncode,
720
+ result.stderr.strip(),
721
+ result.stdout.strip()))
722
+ result.check_returncode()
723
+ temp_filename_pdf = os.path.join(base, temp_filename + '.pdf')
724
+
725
+ # move the pdf into the good location
726
+ if filename:
727
+ filename = os.path.abspath(filename)
728
+ import shutil
729
+ shutil.move(temp_filename_pdf, filename)
730
+ return filename
731
+
732
+ # open the tmp pdf
733
+ elif view:
734
+ from sage.misc.viewer import pdf_viewer
735
+ cmd = pdf_viewer().split()
736
+ cmd.append(temp_filename_pdf)
737
+ # we use check_call as opposed to run, because
738
+ # it gives the sage prompt back to the user
739
+ # see https://stackoverflow.com/a/71342967
740
+ # run(cmd, cwd=base, capture_output=True, check=True)
741
+ from subprocess import check_call, PIPE
742
+ check_call(cmd, cwd=base, stdout=PIPE, stderr=PIPE)
743
+
744
+ return temp_filename_pdf
745
+
746
+ def dvi(self, filename=None, view=True, program='latex'):
747
+ r"""
748
+ Compile the latex code with latex and create a dvi file.
749
+
750
+ INPUT:
751
+
752
+ - ``filename`` -- string (default: ``None``); the output filename.
753
+ If ``None``, it saves the file in a temporary directory
754
+
755
+ - ``view`` -- boolean (default: ``True``); whether to open the file in a
756
+ dvi viewer. This option is ignored and automatically set to
757
+ ``False`` if ``filename`` is not ``None``.
758
+
759
+ - ``program`` -- string (default: ``'latex'``); ``'latex'``
760
+
761
+ OUTPUT: string, path to dvi file
762
+
763
+ EXAMPLES::
764
+
765
+ sage: from sage.misc.latex_standalone import Standalone
766
+ sage: t = Standalone('Hello World')
767
+ sage: _ = t.dvi(view=False) # long time (1s) # optional - latex
768
+
769
+ Same for instances of :class:`TikzPicture`::
770
+
771
+ sage: from sage.misc.latex_standalone import TikzPicture
772
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
773
+ sage: t = TikzPicture(s)
774
+ sage: _ = t.dvi(view=False) # not tested
775
+
776
+ A filename may be provided where to save the file, in which case
777
+ the viewer does not open the file::
778
+
779
+ sage: from sage.misc.temporary_file import tmp_filename
780
+ sage: filename = tmp_filename('temp','.dvi')
781
+ sage: path_to_file = t.dvi(filename) # long time (1s) # optional - latex
782
+ sage: path_to_file[-4:] # long time (fast) # optional - latex
783
+ '.dvi'
784
+
785
+ The filename may contain spaces::
786
+
787
+ sage: filename = tmp_filename('filename with spaces','.dvi')
788
+ sage: path_to_file = t.dvi(filename) # long time (1s) # optional - latex
789
+
790
+ TESTS:
791
+
792
+ We test the behavior when a wrong tex string is provided::
793
+
794
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
795
+ sage: s_missing_last_character = s[:-1]
796
+ sage: t = TikzPicture(s_missing_last_character)
797
+ sage: _ = t.dvi() # optional - latex
798
+ Traceback (most recent call last):
799
+ ...
800
+ CalledProcessError: Command '['latex', '-interaction=nonstopmode',
801
+ 'tikz_...tex']' returned non-zero exit status 1.
802
+
803
+ We test the behavior when a wrong value is provided::
804
+
805
+ sage: t = Standalone('Hello World')
806
+ sage: _ = t.dvi(program='farniente')
807
+ Traceback (most recent call last):
808
+ ...
809
+ ValueError: program(=farniente) should be latex
810
+ """
811
+ from sage.features.latex import latex
812
+
813
+ # Set default program
814
+ if program is None:
815
+ program = 'latex'
816
+
817
+ # Check availability of programs
818
+ if program == 'latex':
819
+ latex().require()
820
+ else:
821
+ raise ValueError("program(={}) should be latex".format(program))
822
+
823
+ # set up filenames
824
+ from sage.misc.temporary_file import tmp_filename
825
+ temp_filename_tex = tmp_filename('tikz_', '.tex')
826
+ with open(temp_filename_tex, 'w') as f:
827
+ f.write(str(self))
828
+ base, temp_filename_tex = os.path.split(temp_filename_tex)
829
+ temp_filename, ext = os.path.splitext(temp_filename_tex)
830
+
831
+ # running pdflatex or lualatex
832
+ cmd = [program, '-interaction=nonstopmode', temp_filename_tex]
833
+ result = run(cmd, cwd=base, capture_output=True, text=True)
834
+
835
+ # If a problem with the tex source occurs, provide the log
836
+ if result.returncode != 0:
837
+ print("Command \n"
838
+ " '{}'\n"
839
+ "returned nonzero exit status {}.\n"
840
+ "Here is the content of the stderr:{}\n"
841
+ "Here is the content of the stdout:"
842
+ "{}\n".format(' '.join(result.args),
843
+ result.returncode,
844
+ result.stderr.strip(),
845
+ result.stdout.strip()))
846
+ result.check_returncode()
847
+ temp_filename_dvi = os.path.join(base, temp_filename + '.dvi')
848
+
849
+ # move the pdf into the good location
850
+ if filename:
851
+ filename = os.path.abspath(filename)
852
+ import shutil
853
+ shutil.move(temp_filename_dvi, filename)
854
+ return filename
855
+
856
+ # open the tmp dvi
857
+ elif view:
858
+ from sage.misc.viewer import dvi_viewer
859
+ cmd = dvi_viewer().split()
860
+ cmd.append(temp_filename_dvi)
861
+ # we use check_call as opposed to run, because
862
+ # it gives the sage prompt back to the user
863
+ # see https://stackoverflow.com/a/71342967
864
+ # run(cmd, cwd=base, capture_output=True, check=True)
865
+ from subprocess import check_call, PIPE
866
+ check_call(cmd, cwd=base, stdout=PIPE, stderr=PIPE)
867
+
868
+ return temp_filename_dvi
869
+
870
+ def png(self, filename=None, density=150, view=True):
871
+ r"""
872
+ Compile the latex code with pdflatex and converts to a png file.
873
+
874
+ INPUT:
875
+
876
+ - ``filename`` -- string (default: ``None``); the output filename.
877
+ If ``None``, it saves the file in a temporary directory.
878
+
879
+ - ``density`` -- integer (default: ``150``); horizontal and vertical
880
+ density of the image
881
+
882
+ - ``view`` -- boolean (default: ``True``); whether to open the file in a
883
+ png viewer. This option is ignored and automatically set to
884
+ ``False`` if ``filename`` is not ``None``.
885
+
886
+ OUTPUT: string, path to png file
887
+
888
+ EXAMPLES::
889
+
890
+ sage: from sage.misc.latex_standalone import Standalone
891
+ sage: t = Standalone('Hello World')
892
+ sage: _ = t.png(view=False) # long time (1s) # optional - latex imagemagick
893
+
894
+ Same for instances of :class:`TikzPicture`::
895
+
896
+ sage: from sage.misc.latex_standalone import TikzPicture
897
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
898
+ sage: t = TikzPicture(s)
899
+ sage: _ = t.png(view=False) # not tested
900
+
901
+ ::
902
+
903
+ sage: from sage.misc.temporary_file import tmp_filename
904
+ sage: filename = tmp_filename('temp','.png')
905
+ sage: path_to_file = t.png(filename) # long time (1s) # optional - latex imagemagick
906
+ sage: path_to_file[-4:] # long time (fast) # optional - latex imagemagick
907
+ '.png'
908
+ """
909
+ from sage.features.imagemagick import ImageMagick
910
+ ImageMagick().require()
911
+
912
+ temp_filename_pdf = self.pdf(filename=None, view=False)
913
+ temp_filename, ext = os.path.splitext(temp_filename_pdf)
914
+ temp_filename_png = temp_filename + '.png'
915
+
916
+ # convert to png
917
+ cmd = ['convert', '-density',
918
+ '{0}x{0}'.format(density), '-trim', temp_filename_pdf,
919
+ temp_filename_png]
920
+ result = run(cmd, capture_output=True, text=True)
921
+
922
+ # If a problem occurs, provide the log
923
+ if result.returncode != 0:
924
+ print("Command \n"
925
+ " '{}'\n"
926
+ "returned nonzero exit status {}.\n"
927
+ "Here is the content of the stderr:{}\n"
928
+ "Here is the content of the stdout:"
929
+ "{}\n".format(' '.join(result.args),
930
+ result.returncode,
931
+ result.stderr.strip(),
932
+ result.stdout.strip()))
933
+ result.check_returncode()
934
+
935
+ # move the png into the good location
936
+ if filename:
937
+ filename = os.path.abspath(filename)
938
+ import shutil
939
+ shutil.move(temp_filename_png, filename)
940
+ return filename
941
+
942
+ # open the tmp png
943
+ elif view:
944
+ from sage.misc.viewer import png_viewer
945
+ cmd = png_viewer().split()
946
+ cmd.append(temp_filename_png)
947
+ # we use check_call as opposed to run, because
948
+ # it gives the sage prompt back to the user
949
+ # see https://stackoverflow.com/a/71342967
950
+ # run(cmd, capture_output=True, check=True)
951
+ from subprocess import check_call, PIPE
952
+ check_call(cmd, stdout=PIPE, stderr=PIPE)
953
+
954
+ return temp_filename_png
955
+
956
+ def svg(self, filename=None, view=True, program='pdftocairo'):
957
+ r"""
958
+ Compile the latex code with pdflatex and converts to a svg file.
959
+
960
+ INPUT:
961
+
962
+ - ``filename`` -- string (default: ``None``); the output filename.
963
+ If ``None``, it saves the file in a temporary directory.
964
+
965
+ - ``view`` -- boolean (default: ``True``); whether to open the file in
966
+ a browser. This option is ignored and automatically set to
967
+ ``False`` if ``filename`` is not ``None``.
968
+
969
+ - ``program`` -- string (default: ``'pdftocairo'``); ``'pdftocairo'`` or
970
+ ``'pdf2svg'``
971
+
972
+ OUTPUT: string, path to svg file
973
+
974
+ EXAMPLES::
975
+
976
+ sage: from sage.misc.latex_standalone import Standalone
977
+ sage: t = Standalone('Hello World')
978
+ sage: _ = t.svg(view=False) # not tested
979
+
980
+ Same for instances of :class:`TikzPicture`::
981
+
982
+ sage: from sage.misc.latex_standalone import TikzPicture
983
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
984
+ sage: t = TikzPicture(s)
985
+ sage: _ = t.svg(view=False) # not tested
986
+
987
+ ::
988
+
989
+ sage: from sage.misc.temporary_file import tmp_filename
990
+ sage: filename = tmp_filename('temp', '.svg')
991
+ sage: path_to_file = t.svg(filename, # long time (1s) # optional - latex pdf2svg
992
+ ....: program='pdf2svg')
993
+ sage: path_to_file[-4:] # long time (fast) # optional - latex pdf2svg
994
+ '.svg'
995
+ sage: path_to_file = t.svg(filename, # long time (1s) # optional - latex pdftocairo
996
+ ....: program='pdftocairo')
997
+ sage: path_to_file[-4:] # long time (fast) # optional - latex pdftocairo
998
+ '.svg'
999
+ """
1000
+ # set the temporary filenames
1001
+ temp_filename_pdf = self.pdf(filename=None, view=False)
1002
+ temp_filename, ext = os.path.splitext(temp_filename_pdf)
1003
+ temp_filename_svg = temp_filename + '.svg'
1004
+
1005
+ # set the command
1006
+ if program == 'pdftocairo':
1007
+ from sage.features.poppler import pdftocairo
1008
+ pdftocairo().require()
1009
+ cmd = ['pdftocairo', '-svg', temp_filename_pdf, temp_filename_svg]
1010
+ elif program == 'pdf2svg':
1011
+ from sage.features.pdf2svg import pdf2svg
1012
+ pdf2svg().require()
1013
+ cmd = ['pdf2svg', temp_filename_pdf, temp_filename_svg]
1014
+ else:
1015
+ raise ValueError("program(={}) should be 'pdftocairo' or"
1016
+ " 'pdf2svg'".format(program))
1017
+
1018
+ # convert to svg
1019
+ result = run(cmd, capture_output=True, text=True)
1020
+
1021
+ # If a problem occurs, provide the log
1022
+ if result.returncode != 0:
1023
+ print("Command \n"
1024
+ " '{}'\n"
1025
+ "returned nonzero exit status {}.\n"
1026
+ "Here is the content of the stderr:{}\n"
1027
+ "Here is the content of the stdout:"
1028
+ "{}\n".format(' '.join(result.args),
1029
+ result.returncode,
1030
+ result.stderr.strip(),
1031
+ result.stdout.strip()))
1032
+ result.check_returncode()
1033
+
1034
+ # move the svg into the good location
1035
+ if filename:
1036
+ filename = os.path.abspath(filename)
1037
+ import shutil
1038
+ shutil.move(temp_filename_svg, filename)
1039
+ return filename
1040
+
1041
+ # open the tmp svg
1042
+ elif view:
1043
+ from sage.misc.viewer import browser
1044
+ cmd = browser().split()
1045
+ cmd.append(temp_filename_svg)
1046
+ # we use check_call as opposed to run, because
1047
+ # it gives the sage prompt back to the user
1048
+ # see https://stackoverflow.com/a/71342967
1049
+ # run(cmd, capture_output=True, check=True)
1050
+ from subprocess import check_call, PIPE
1051
+ check_call(cmd, stdout=PIPE, stderr=PIPE)
1052
+
1053
+ return temp_filename_svg
1054
+
1055
+ def eps(self, filename=None, view=True, program='dvips'):
1056
+ r"""
1057
+ Compile the latex code with pdflatex and converts to a eps file.
1058
+
1059
+ INPUT:
1060
+
1061
+ - ``filename`` -- string (default: ``None``); the output filename.
1062
+ If ``None``, it saves the file in a temporary directory
1063
+
1064
+ - ``view`` -- boolean (default: ``True``); whether to open the file in
1065
+ a browser. This option is ignored and automatically set to
1066
+ ``False`` if ``filename`` is not ``None``.
1067
+
1068
+ - ``program`` -- string (default: ``'dvips'``);
1069
+ ``'pdftocairo'`` or ``'dvips'``
1070
+
1071
+ OUTPUT: string, path to eps file
1072
+
1073
+ EXAMPLES::
1074
+
1075
+ sage: from sage.misc.latex_standalone import Standalone
1076
+ sage: t = Standalone('Hello World')
1077
+ sage: _ = t.eps(view=False) # not tested
1078
+
1079
+ Same for instances of :class:`TikzPicture`::
1080
+
1081
+ sage: from sage.misc.latex_standalone import TikzPicture
1082
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
1083
+ sage: t = TikzPicture(s)
1084
+ sage: _ = t.eps(view=False) # not tested
1085
+
1086
+ We test the creation of the files::
1087
+
1088
+ sage: from sage.misc.temporary_file import tmp_filename
1089
+ sage: filename = tmp_filename('temp', '.eps')
1090
+ sage: path_to_file = t.eps(filename, # long time (1s) # optional - latex dvips
1091
+ ....: program='dvips')
1092
+ sage: path_to_file[-4:] # long time (fast) # optional - latex dvips
1093
+ '.eps'
1094
+ sage: path_to_file = t.eps(filename, # long time (1s) # optional - latex pdftocairo
1095
+ ....: program='pdftocairo')
1096
+ sage: path_to_file[-4:] # long time (fast) # optional - latex pdftocairo
1097
+ '.eps'
1098
+
1099
+ TESTS:
1100
+
1101
+ We test the behavior when a wrong value is provided::
1102
+
1103
+ sage: t = Standalone('Hello World')
1104
+ sage: _ = t.eps(program='convert')
1105
+ Traceback (most recent call last):
1106
+ ...
1107
+ ValueError: program(=convert) should be 'pdftocairo' or 'dvips'
1108
+ """
1109
+
1110
+ if program == 'pdftocairo':
1111
+ from sage.features.poppler import pdftocairo
1112
+ pdftocairo().require()
1113
+ # set the temporary filenames
1114
+ temp_filename_pdf = self.pdf(filename=None, view=False)
1115
+ temp_filename, ext = os.path.splitext(temp_filename_pdf)
1116
+ temp_filename_eps = temp_filename + '.eps'
1117
+ # set the command
1118
+ cmd = ['pdftocairo', '-eps', temp_filename_pdf, temp_filename_eps]
1119
+ elif program == 'dvips':
1120
+ from sage.features.latex import dvips
1121
+ dvips().require()
1122
+ # set the temporary filenames
1123
+ temp_filename_dvi = self.dvi(filename=None, view=False)
1124
+ temp_filename, ext = os.path.splitext(temp_filename_dvi)
1125
+ temp_filename_eps = temp_filename + '.eps'
1126
+ # set the command
1127
+ cmd = ['dvips', '-E', '-o', temp_filename_eps, temp_filename_dvi]
1128
+ else:
1129
+ raise ValueError("program(={}) should be 'pdftocairo' or"
1130
+ " 'dvips'".format(program))
1131
+
1132
+ # convert to eps
1133
+ result = run(cmd, capture_output=True, text=True)
1134
+
1135
+ # If a problem occurs, provide the log
1136
+ if result.returncode != 0:
1137
+ print("Command \n"
1138
+ " '{}'\n"
1139
+ "returned nonzero exit status {}.\n"
1140
+ "Here is the content of the stderr:{}\n"
1141
+ "Here is the content of the stdout:"
1142
+ "{}\n".format(' '.join(result.args),
1143
+ result.returncode,
1144
+ result.stderr.strip(),
1145
+ result.stdout.strip()))
1146
+ result.check_returncode()
1147
+
1148
+ # move the eps into the good location
1149
+ if filename:
1150
+ filename = os.path.abspath(filename)
1151
+ import shutil
1152
+ shutil.move(temp_filename_eps, filename)
1153
+ return filename
1154
+
1155
+ # open the tmp eps
1156
+ elif view:
1157
+ from sage.misc.viewer import viewer
1158
+ cmd = viewer().split()
1159
+ cmd.append(temp_filename_eps)
1160
+ # we use check_call as opposed to run, because
1161
+ # it gives the sage prompt back to the user
1162
+ # see https://stackoverflow.com/a/71342967
1163
+ # run(cmd, capture_output=True, check=True)
1164
+ from subprocess import check_call, PIPE
1165
+ check_call(cmd, stdout=PIPE, stderr=PIPE)
1166
+
1167
+ return temp_filename_eps
1168
+
1169
+ def tex(self, filename=None, content_only=False, include_header=None):
1170
+ r"""
1171
+ Writes the latex code to a file.
1172
+
1173
+ INPUT:
1174
+
1175
+ - ``filename`` -- string (default: ``None``); the output filename.
1176
+ If ``None``, it saves the file in a temporary directory.
1177
+ - ``content_only`` -- boolean (default: ``False``); whether to include
1178
+ the header latex part. If ``True``, it prints only the
1179
+ content to the file.
1180
+
1181
+ OUTPUT: string, path to tex file
1182
+
1183
+ EXAMPLES::
1184
+
1185
+ sage: from sage.misc.latex_standalone import Standalone
1186
+ sage: t = Standalone('Hello World')
1187
+ sage: _ = t.tex()
1188
+ sage: _ = t.tex(content_only=True)
1189
+
1190
+ Same for instances of :class:`TikzPicture`::
1191
+
1192
+ sage: from sage.misc.latex_standalone import TikzPicture
1193
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
1194
+ sage: t = TikzPicture(s)
1195
+ sage: _ = t.tex()
1196
+ sage: _ = t.tex(content_only=True)
1197
+
1198
+ Write to a given filename::
1199
+
1200
+ sage: from sage.misc.temporary_file import tmp_filename
1201
+ sage: filename = tmp_filename('temp','.tex')
1202
+ sage: path_to_file = t.tex(filename)
1203
+ sage: path_to_file[-4:]
1204
+ '.tex'
1205
+ """
1206
+ if filename is None:
1207
+ from sage.misc.temporary_file import tmp_filename
1208
+ filename = tmp_filename('tikz_', '.tex')
1209
+ else:
1210
+ filename = os.path.abspath(filename)
1211
+
1212
+ if include_header is not None:
1213
+ content_only = not include_header
1214
+ from sage.misc.superseded import deprecation
1215
+ deprecation(20343, "When merging this code from slabbe into "
1216
+ "SageMath the argument include_header=False was "
1217
+ "replaced by content_only=True. Please update your code "
1218
+ "before include_header option gets removed from SageMath.")
1219
+
1220
+ if content_only:
1221
+ output = self.content()
1222
+ else:
1223
+ output = str(self)
1224
+
1225
+ with open(filename, 'w') as f:
1226
+ f.write(output)
1227
+
1228
+ return filename
1229
+
1230
+ def save(self, filename, **kwds):
1231
+ r"""
1232
+ Save the graphics to an image file.
1233
+
1234
+ INPUT:
1235
+
1236
+ - ``filename`` -- string. The filename and the image format
1237
+ given by the extension, which can be one of the following:
1238
+
1239
+ * ``.pdf``,
1240
+ * ``.png``,
1241
+ * ``.svg``,
1242
+ * ``.eps``,
1243
+ * ``.dvi``,
1244
+ * ``.sobj`` (for a Sage object you can load later),
1245
+ * empty extension will be treated as ``.sobj``.
1246
+
1247
+ All other keyword arguments will be passed to the plotter.
1248
+
1249
+ OUTPUT: none
1250
+
1251
+ .. NOTE::
1252
+
1253
+ This method follows the signature of the method
1254
+ :meth:`sage.plot.Graphics.save` in order to be compatible with
1255
+ with sagetex. In particular so that ``\sageplot{t}`` written
1256
+ in a ``tex`` file works when ``t`` is an instance of
1257
+ :class:`Standalone` or :class:`TikzPicture`.
1258
+
1259
+ EXAMPLES::
1260
+
1261
+ sage: from sage.misc.temporary_file import tmp_filename
1262
+ sage: from sage.misc.latex_standalone import Standalone
1263
+ sage: t = Standalone('Hello World')
1264
+ sage: filename = tmp_filename('temp','.pdf')
1265
+ sage: t.save(filename) # long time (1s) # optional - latex
1266
+ sage: filename = tmp_filename('temp','.eps')
1267
+ sage: t.save(filename) # long time (1s) # optional - latex dvips
1268
+ """
1269
+ ext = os.path.splitext(filename)[1].lower()
1270
+ if ext == '' or ext == '.sobj':
1271
+ raise NotImplementedError()
1272
+ elif ext == '.pdf':
1273
+ self.pdf(filename, **kwds)
1274
+ elif ext == '.png':
1275
+ self.png(filename, **kwds)
1276
+ elif ext == '.svg':
1277
+ self.svg(filename, **kwds)
1278
+ elif ext == '.eps':
1279
+ self.eps(filename, **kwds)
1280
+ elif ext == '.dvi':
1281
+ self.dvi(filename, **kwds)
1282
+ else:
1283
+ raise ValueError("allowed file extensions for images are "
1284
+ ".pdf, .png, .svg, .eps, .dvi!")
1285
+
1286
+
1287
+ class TikzPicture(Standalone):
1288
+ r"""
1289
+ A TikzPicture embedded in a LaTeX standalone document class.
1290
+
1291
+ INPUT:
1292
+
1293
+ - ``content`` -- string, tikzpicture code starting with ``r'\begin{tikzpicture}'``
1294
+ and ending with ``r'\end{tikzpicture}'``
1295
+ - ``standalone_config`` -- list of strings (default: ``[]``);
1296
+ latex document class standalone configuration options
1297
+ - ``usepackage`` -- list of strings (default: ``[]``); latex
1298
+ packages
1299
+ - ``usetikzlibrary`` -- list of strings (default: ``[]``); tikz libraries
1300
+ to use
1301
+ - ``macros`` -- list of strings (default: ``[]``); stuff you need for the picture
1302
+ - ``use_sage_preamble`` -- boolean (default: ``False``); whether to include sage
1303
+ latex preamble and sage latex macros, that is, the content of
1304
+ :func:`sage.misc.latex.extra_preamble()`,
1305
+ :func:`sage.misc.latex.extra_macros()` and
1306
+ :func:`sage.misc.latex_macros.sage_latex_macros()`
1307
+
1308
+ EXAMPLES:
1309
+
1310
+ Create your own tikz string from scratch and provide it::
1311
+
1312
+ sage: from sage.misc.latex_standalone import TikzPicture
1313
+ sage: lines = []
1314
+ sage: lines.append(r'\begin{tikzpicture}')
1315
+ sage: lines.append(r'\draw[very thick,orange,->] (0,0) -- (1,1);')
1316
+ sage: lines.append(r'\end{tikzpicture}')
1317
+ sage: s = '\n'.join(lines)
1318
+ sage: t = TikzPicture(s)
1319
+ sage: t
1320
+ \documentclass[tikz]{standalone}
1321
+ \begin{document}
1322
+ \begin{tikzpicture}
1323
+ \draw[very thick,orange,->] (0,0) -- (1,1);
1324
+ \end{tikzpicture}
1325
+ \end{document}
1326
+
1327
+ Then use it by exporting the tikzpicture to other formats, all of the
1328
+ below methods return a string providing the path to the filename, which
1329
+ is by default in a temporary folder::
1330
+
1331
+ sage: # not tested
1332
+ sage: _ = t.pdf()
1333
+ sage: _ = t.png()
1334
+ sage: _ = t.svg()
1335
+ sage: _ = t.tex()
1336
+ sage: _ = t.pdf(filename='abc.pdf')
1337
+
1338
+ Here we create a tikzpicture for the latex representation of a graph.
1339
+ This is using tkz-graph tex library::
1340
+
1341
+ sage: # needs sage.graphs
1342
+ sage: g = graphs.PetersenGraph()
1343
+ sage: s = latex(g) # optional - latex
1344
+ sage: t = TikzPicture(s, standalone_config=["border=4mm"], # optional - latex
1345
+ ....: usepackage=['tkz-graph'])
1346
+ sage: _ = t.pdf(view=False) # long time (2s), optional - latex latex_package_tkz_graph
1347
+
1348
+ Here are standalone configurations, packages, tikz libraries and macros
1349
+ that can be set::
1350
+
1351
+ sage: options = ['preview', 'border=4mm', 'beamer', 'float']
1352
+ sage: usepackage = ['nicefrac', 'amsmath', 'pifont', 'tikz-3dplot',
1353
+ ....: 'pgfplots']
1354
+ sage: tikzlib = ['arrows', 'snakes', 'backgrounds', 'patterns',
1355
+ ....: 'matrix', 'shapes', 'fit', 'calc', 'shadows', 'plotmarks',
1356
+ ....: 'positioning', 'pgfplots.groupplots', 'mindmap']
1357
+ sage: macros = [r'\newcommand{\ZZ}{\mathbb{Z}}']
1358
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
1359
+ sage: t = TikzPicture(s, standalone_config=options, usepackage=usepackage,
1360
+ ....: usetikzlibrary=tikzlib, macros=macros)
1361
+ sage: _ = t.pdf(view=False) # long time (2s), optional - latex
1362
+ """
1363
+ def __init__(self, content, standalone_config=None, usepackage=None,
1364
+ usetikzlibrary=None, macros=None, use_sage_preamble=False):
1365
+ r"""
1366
+ See :class:`TikzPicture` for full information.
1367
+
1368
+ EXAMPLES::
1369
+
1370
+ sage: from sage.misc.latex_standalone import TikzPicture
1371
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
1372
+ sage: t = TikzPicture(s)
1373
+ """
1374
+ Standalone.__init__(self, content, document_class_options=['tikz'],
1375
+ standalone_config=standalone_config, usepackage=usepackage,
1376
+ macros=macros, use_sage_preamble=use_sage_preamble)
1377
+
1378
+ self._usetikzlibrary = [] if usetikzlibrary is None else usetikzlibrary
1379
+
1380
+ def _latex_file_header_lines(self):
1381
+ r"""
1382
+ EXAMPLES::
1383
+
1384
+ sage: latex.extra_preamble('')
1385
+ sage: from sage.misc.latex_standalone import TikzPicture
1386
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
1387
+ sage: t = TikzPicture(s, standalone_config=["border=4mm"], usepackage=['tkz-graph'])
1388
+ sage: t._latex_file_header_lines()[:6]
1389
+ ['\\documentclass[tikz]{standalone}',
1390
+ '\\standaloneconfig{border=4mm}',
1391
+ '\\usepackage{tkz-graph}']
1392
+ """
1393
+ lines = Standalone._latex_file_header_lines(self)
1394
+ for library in self._usetikzlibrary:
1395
+ lines.append(r"\usetikzlibrary{{{}}}".format(library))
1396
+ return lines
1397
+
1398
+ def add_usetikzlibrary(self, library):
1399
+ r"""
1400
+ Add a ``usetikzlibrary`` line.
1401
+
1402
+ INPUT:
1403
+
1404
+ - ``library`` -- string, name of library
1405
+
1406
+ EXAMPLES::
1407
+
1408
+ sage: from sage.misc.latex_standalone import TikzPicture
1409
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
1410
+ sage: t = TikzPicture(s)
1411
+ sage: t.add_usetikzlibrary('arrows')
1412
+ sage: t
1413
+ \documentclass[tikz]{standalone}
1414
+ \usetikzlibrary{arrows}
1415
+ \begin{document}
1416
+ \begin{tikzpicture}
1417
+ \draw (0,0) -- (1,1);
1418
+ \end{tikzpicture}
1419
+ \end{document}
1420
+ """
1421
+ self._usetikzlibrary.append(library)
1422
+
1423
+ @classmethod
1424
+ def from_dot_string(cls, dotdata, prog='dot'):
1425
+ r"""
1426
+ Convert a graph to a tikzpicture using graphviz and dot2tex.
1427
+
1428
+ .. NOTE::
1429
+
1430
+ Prerequisite: dot2tex optional Sage package and graphviz must be
1431
+ installed.
1432
+
1433
+ INPUT:
1434
+
1435
+ - ``dotdata`` -- dot format string
1436
+ - ``prog`` -- string (default: ``'dot'``); the program used for the
1437
+ layout corresponding to one of the software of the graphviz
1438
+ suite: ``'dot'``, ``'neato'``, ``'twopi'``, ``'circo'`` or ``'fdp'``
1439
+
1440
+ EXAMPLES::
1441
+
1442
+ sage: # needs sage.graphs
1443
+ sage: from sage.misc.latex_standalone import TikzPicture
1444
+ sage: G = graphs.PetersenGraph()
1445
+ sage: dotdata = G.graphviz_string()
1446
+ sage: tikz = TikzPicture.from_dot_string(dotdata) # long time (3s), optional - dot2tex graphviz
1447
+ sage: _ = tikz.pdf() # not tested
1448
+
1449
+ ::
1450
+
1451
+ sage: # needs sage.graphs
1452
+ sage: dotdata = G.graphviz_string(labels='latex')
1453
+ sage: tikz = TikzPicture.from_dot_string(dotdata) # long time (3s), optional - dot2tex graphviz
1454
+ sage: _ = tikz.pdf() # not tested
1455
+
1456
+ ::
1457
+
1458
+ sage: # needs sage.combinat sage.graphs sage.groups
1459
+ sage: W = CoxeterGroup(["A",2])
1460
+ sage: G = W.cayley_graph()
1461
+ sage: dotdata = G.graphviz_string()
1462
+ sage: tikz = TikzPicture.from_dot_string(dotdata) # long time (3s), optional - dot2tex graphviz
1463
+ sage: _ = tikz.pdf() # not tested
1464
+
1465
+ ::
1466
+
1467
+ sage: # needs sage.combinat sage.graphs sage.groups
1468
+ sage: dotdata = G.graphviz_string(labels='latex')
1469
+ sage: tikz = TikzPicture.from_dot_string(dotdata) # long time (3s), optional - dot2tex graphviz
1470
+ sage: _ = tikz.pdf() # not tested
1471
+ """
1472
+ from sage.features import PythonModule
1473
+ PythonModule("dot2tex").require()
1474
+ from sage.features.graphviz import Graphviz
1475
+ Graphviz().require()
1476
+
1477
+ import dot2tex
1478
+ tikz = dot2tex.dot2tex(dotdata,
1479
+ format='tikz',
1480
+ autosize=True,
1481
+ crop=True,
1482
+ figonly='True',
1483
+ prog=prog).strip()
1484
+ return TikzPicture(tikz, standalone_config=["border=4mm"],
1485
+ usetikzlibrary=['shapes'])
1486
+
1487
+ @classmethod
1488
+ @experimental(issue_number=20343)
1489
+ def from_graph(cls, graph, merge_multiedges=True,
1490
+ merge_label_function=tuple, **kwds):
1491
+ r"""
1492
+ Convert a graph to a tikzpicture using graphviz and dot2tex.
1493
+
1494
+ .. NOTE::
1495
+
1496
+ Prerequisite: dot2tex optional Sage package and graphviz must be
1497
+ installed.
1498
+
1499
+ .. WARNING::
1500
+
1501
+ This method might be deleted in the future in favor of a method
1502
+ in the graph class returning a tikz picture.
1503
+
1504
+ INPUT:
1505
+
1506
+ - ``graph`` -- graph
1507
+ - ``merge_multiedges`` -- boolean (default: ``True``); if the graph
1508
+ has multiple edges, whether to merge the multiedges into one
1509
+ single edge
1510
+ - ``merge_label_function`` -- function (default: ``tuple``); a
1511
+ function to apply to each list of labels to be merged. It is
1512
+ ignored if ``merge_multiedges`` is not ``True`` or if the graph
1513
+ has no multiple edges.
1514
+
1515
+ Other inputs are used for latex drawing with dot2tex and graphviz:
1516
+
1517
+ - ``prog`` -- string (default: ``'dot'``); the program used for the
1518
+ layout corresponding to one of the software of the graphviz
1519
+ suite: ``'dot'``, ``'neato'``, ``'twopi'``, ``'circo'`` or ``'fdp'``
1520
+ - ``edge_labels`` -- boolean (default: ``True``)
1521
+ - ``color_by_label`` -- boolean (default: ``False``)
1522
+ - ``rankdir`` -- string (default: ``'down'``)
1523
+ - ``subgraph_clusters`` -- (default: ``[]``) a list of lists of
1524
+ vertices, if supported by the layout engine, nodes belonging to
1525
+ the same cluster subgraph are drawn together, with the entire
1526
+ drawing of the cluster contained within a bounding rectangle.
1527
+
1528
+ EXAMPLES::
1529
+
1530
+ sage: # needs sage.graphs
1531
+ sage: from sage.misc.latex_standalone import TikzPicture
1532
+ sage: g = graphs.PetersenGraph()
1533
+ sage: tikz = TikzPicture.from_graph(g) # optional - dot2tex graphviz
1534
+ doctest:...: FutureWarning: This class/method/function is marked as experimental.
1535
+ It, its functionality or its interface might change without a formal deprecation.
1536
+ See https://github.com/sagemath/sage/issues/20343 for details.
1537
+ sage: _ = tikz.pdf() # not tested
1538
+
1539
+ Using ``prog``::
1540
+
1541
+ sage: # needs sage.graphs
1542
+ sage: tikz = TikzPicture.from_graph(g, prog='neato', # long time (3s), optional - dot2tex graphviz
1543
+ ....: color_by_label=True)
1544
+ sage: _ = tikz.pdf() # not tested
1545
+
1546
+ Using ``rankdir``::
1547
+
1548
+ sage: tikz = TikzPicture.from_graph(g, rankdir='right') # long time (3s), optional - dot2tex graphviz, needs sage.graphs
1549
+ sage: _ = tikz.pdf() # not tested
1550
+
1551
+ Using ``merge_multiedges``::
1552
+
1553
+ sage: # needs sage.graphs sage.modules sage.symbolic
1554
+ sage: alpha = var('alpha')
1555
+ sage: m = matrix(2, range(4)); m.set_immutable()
1556
+ sage: G = DiGraph([(0,1,alpha), (0,1,0), (0,2,9), (0,2,m)],
1557
+ ....: multiedges=True)
1558
+ sage: tikz = TikzPicture.from_graph(G, merge_multiedges=True) # optional - dot2tex graphviz
1559
+ sage: _ = tikz.pdf() # not tested
1560
+
1561
+ Using ``merge_multiedges`` with ``merge_label_function``::
1562
+
1563
+ sage: # needs sage.graphs
1564
+ sage: fn = lambda L: LatexExpr(','.join(map(str, L)))
1565
+ sage: edges = [(0,1,'a'), (0,1,'b'), (0,2,'c'), (0,2,'d')]
1566
+ sage: G = DiGraph(edges, multiedges=True)
1567
+ sage: tikz = TikzPicture.from_graph(G, # optional - dot2tex graphviz
1568
+ ....: merge_multiedges=True, merge_label_function=fn)
1569
+ sage: _ = tikz.pdf() # not tested
1570
+
1571
+ Using subgraphs clusters (broken when using labels, see
1572
+ :issue:`22070`)::
1573
+
1574
+ sage: S = FiniteSetMaps(5)
1575
+ sage: I = S((0,1,2,3,4))
1576
+ sage: a = S((0,1,3,0,0))
1577
+ sage: b = S((0,2,4,1,0))
1578
+ sage: roots = [I]
1579
+ sage: succ = lambda v: [v*a,v*b,a*v,b*v]
1580
+ sage: R = RecursivelyEnumeratedSet(roots, succ)
1581
+ sage: G = R.to_digraph() # needs sage.graphs
1582
+ sage: G # needs sage.graphs
1583
+ Looped multi-digraph on 27 vertices
1584
+ sage: C = G.strongly_connected_components() # needs sage.graphs
1585
+ sage: tikz = TikzPicture.from_graph(G, # optional - dot2tex graphviz, needs sage.graphs
1586
+ ....: merge_multiedges=False, subgraph_clusters=C)
1587
+ sage: _ = tikz.pdf() # not tested
1588
+
1589
+ An example coming from ``graphviz_string`` documentation in SageMath::
1590
+
1591
+ sage: # needs sage.graphs sage.symbolic
1592
+ sage: f(x) = -1 / x
1593
+ sage: g(x) = 1 / (x + 1)
1594
+ sage: G = DiGraph()
1595
+ sage: G.add_edges((i, f(i), f) for i in (1, 2, 1/2, 1/4))
1596
+ sage: G.add_edges((i, g(i), g) for i in (1, 2, 1/2, 1/4))
1597
+ sage: tikz = TikzPicture.from_graph(G) # optional - dot2tex graphviz
1598
+ sage: _ = tikz.pdf() # not tested
1599
+ sage: def edge_options(data):
1600
+ ....: u, v, label = data
1601
+ ....: options = {"color": {f: "red", g: "blue"}[label]}
1602
+ ....: if (u,v) == (1/2, -2): options["label"] = "coucou"; options["label_style"] = "string"
1603
+ ....: if (u,v) == (1/2,2/3): options["dot"] = "x=1,y=2"
1604
+ ....: if (u,v) == (1, -1): options["label_style"] = "latex"
1605
+ ....: if (u,v) == (1, 1/2): options["dir"] = "back"
1606
+ ....: return options
1607
+ sage: tikz = TikzPicture.from_graph(G, edge_options=edge_options) # optional - dot2tex graphviz
1608
+ sage: _ = tikz.pdf() # not tested
1609
+ """
1610
+ from sage.features.latex import pdflatex
1611
+ pdflatex().require()
1612
+ from sage.features.graphviz import Graphviz
1613
+ Graphviz().require()
1614
+ from sage.features import PythonModule
1615
+ PythonModule("dot2tex").require()
1616
+
1617
+ if merge_multiedges and graph.has_multiple_edges():
1618
+ from collections import defaultdict
1619
+ d = defaultdict(list)
1620
+ for (u, v, label) in graph.edges(sort=False):
1621
+ d[(u, v)].append(label)
1622
+ edges = [(u, v, merge_label_function(label_list)) for (u, v), label_list in d.items()]
1623
+ loops = graph.has_loops()
1624
+ if graph.is_directed():
1625
+ from sage.graphs.digraph import DiGraph
1626
+ graph = DiGraph(edges, format='list_of_edges', loops=loops)
1627
+ else:
1628
+ from sage.graphs.graph import Graph
1629
+ graph = Graph(edges, format='list_of_edges', loops=loops)
1630
+
1631
+ options = {'format': 'dot2tex', 'edge_labels': True,
1632
+ 'color_by_label': False, 'prog': 'dot', 'rankdir': 'down'}
1633
+ options.update(kwds)
1634
+
1635
+ graph.latex_options().set_options(**options)
1636
+ tikz = graph._latex_()
1637
+ return TikzPicture(tikz, standalone_config=["border=4mm"])
1638
+
1639
+ @classmethod
1640
+ @experimental(issue_number=20343)
1641
+ def from_graph_with_pos(cls, graph, scale=1, merge_multiedges=True,
1642
+ merge_label_function=tuple):
1643
+ r"""
1644
+ Convert a graph with positions defined for vertices to a tikzpicture.
1645
+
1646
+ .. WARNING::
1647
+
1648
+ This method might be deleted in the future in favor of a method
1649
+ in the graph class returning a tikz picture.
1650
+
1651
+ INPUT:
1652
+
1653
+ - ``graph`` -- graph (with predefined positions)
1654
+ - ``scale`` -- number (default: ``1``); tikzpicture scale
1655
+ - ``merge_multiedges`` -- boolean (default: ``True``); if the graph
1656
+ has multiple edges, whether to merge the multiedges into one
1657
+ single edge
1658
+ - ``merge_label_function`` -- function (default: ``tuple``); a
1659
+ function to apply to each list of labels to be merged. It is
1660
+ ignored if ``merge_multiedges`` is not ``True`` or if the graph
1661
+ has no multiple edges.
1662
+
1663
+ EXAMPLES::
1664
+
1665
+ sage: from sage.misc.latex_standalone import TikzPicture
1666
+
1667
+ sage: # needs sage.graphs
1668
+ sage: g = graphs.PetersenGraph()
1669
+ sage: tikz = TikzPicture.from_graph_with_pos(g)
1670
+ doctest:...: FutureWarning: This class/method/function is marked as experimental.
1671
+ It, its functionality or its interface might change without a formal deprecation.
1672
+ See https://github.com/sagemath/sage/issues/20343 for details.
1673
+
1674
+ ::
1675
+
1676
+ sage: # needs sage.graphs
1677
+ sage: edges = [(0,0,'a'),(0,1,'b'),(0,1,'c')]
1678
+ sage: kwds = dict(format='list_of_edges', loops=True, multiedges=True)
1679
+ sage: G = DiGraph(edges, **kwds)
1680
+ sage: G.set_pos({0:(0,0), 1:(1,0)})
1681
+ sage: f = lambda label:','.join(label)
1682
+ sage: TikzPicture.from_graph_with_pos(G, merge_label_function=f)
1683
+ \documentclass[tikz]{standalone}
1684
+ \standaloneconfig{border=4mm}
1685
+ \begin{document}
1686
+ \begin{tikzpicture}
1687
+ [auto,scale=1]
1688
+ % vertices
1689
+ \node (node_0) at (0, 0) {0};
1690
+ \node (node_1) at (1, 0) {1};
1691
+ % edges
1692
+ \draw[->] (node_0) -- node {b,c} (node_1);
1693
+ % loops
1694
+ \draw (node_0) edge [loop above] node {a} ();
1695
+ \end{tikzpicture}
1696
+ \end{document}
1697
+
1698
+ TESTS::
1699
+
1700
+ sage: # needs sage.graphs
1701
+ sage: edges = [(0,0,'a'),(0,1,'b'),(0,1,'c')]
1702
+ sage: kwds = dict(format='list_of_edges', loops=True, multiedges=True)
1703
+ sage: G = DiGraph(edges, **kwds)
1704
+ sage: TikzPicture.from_graph_with_pos(G)
1705
+ Traceback (most recent call last):
1706
+ ...
1707
+ ValueError: vertex positions need to be set first
1708
+ """
1709
+ pos = graph.get_pos()
1710
+ if pos is None:
1711
+ raise ValueError('vertex positions need to be set first')
1712
+
1713
+ if merge_multiedges and graph.has_multiple_edges():
1714
+ from collections import defaultdict
1715
+ d = defaultdict(list)
1716
+ for (u, v, label) in graph.edges(sort=True):
1717
+ d[(u, v)].append(label)
1718
+ edges = [(u, v, merge_label_function(label_list)) for (u, v), label_list in d.items()]
1719
+ loops = graph.has_loops()
1720
+ if graph.is_directed():
1721
+ from sage.graphs.digraph import DiGraph
1722
+ graph = DiGraph(edges, format='list_of_edges', loops=loops)
1723
+ else:
1724
+ from sage.graphs.graph import Graph
1725
+ graph = Graph(edges, format='list_of_edges', loops=loops)
1726
+
1727
+ keys_for_vertices = graph._keys_for_vertices()
1728
+
1729
+ lines = []
1730
+ lines.append(r'\begin{tikzpicture}')
1731
+ lines.append(r'[auto,scale={}]'.format(scale))
1732
+
1733
+ # vertices
1734
+ lines.append(r'% vertices')
1735
+ for u in graph.vertices(sort=False):
1736
+ line = r'\node ({}) at {} {{{}}};'.format(keys_for_vertices(u),
1737
+ pos[u], u)
1738
+ lines.append(line)
1739
+
1740
+ # edges
1741
+ lines.append(r'% edges')
1742
+ arrow = '->' if graph.is_directed() else ''
1743
+ for (u, v, label) in graph.edges(sort=True):
1744
+ if u == v:
1745
+ # loops are done below
1746
+ continue
1747
+ if label:
1748
+ line = r'\draw[{}] ({}) -- node {{{}}} ({});'.format(arrow,
1749
+ keys_for_vertices(u),
1750
+ label,
1751
+ keys_for_vertices(v))
1752
+ else:
1753
+ line = r'\draw[{}] ({}) -- ({});'.format(arrow,
1754
+ keys_for_vertices(u),
1755
+ keys_for_vertices(v))
1756
+ lines.append(line)
1757
+
1758
+ # loops
1759
+ lines.append(r'% loops')
1760
+ for (u, v, label) in graph.loop_edges():
1761
+ line = r'\draw ({}) edge [loop above] node {{{}}} ();'.format(
1762
+ keys_for_vertices(u), label)
1763
+ lines.append(line)
1764
+
1765
+ lines.append(r'\end{tikzpicture}')
1766
+ tikz = '\n'.join(lines)
1767
+ return TikzPicture(tikz, standalone_config=["border=4mm"])
1768
+
1769
+ @classmethod
1770
+ @experimental(issue_number=20343)
1771
+ def from_poset(cls, poset, **kwds):
1772
+ r"""
1773
+ Convert a poset to a tikzpicture using graphviz and dot2tex.
1774
+
1775
+ .. NOTE::
1776
+
1777
+ Prerequisite: dot2tex optional Sage package and graphviz must be
1778
+ installed.
1779
+
1780
+ .. WARNING::
1781
+
1782
+ This method might be deleted in the future in favor of a method
1783
+ in the graph class returning a tikz picture.
1784
+
1785
+ INPUT:
1786
+
1787
+ - ``poset`` -- poset
1788
+ - ``prog`` -- string (default: ``'dot'``); the program used for the
1789
+ layout corresponding to one of the software of the graphviz
1790
+ suite: ``'dot'``, ``'neato'``, ``'twopi'``, ``'circo'`` or ``'fdp'``
1791
+ - ``edge_labels`` -- boolean (default: ``True``)
1792
+ - ``color_by_label`` -- boolean (default: ``False``)
1793
+ - ``rankdir`` -- string (default: ``'down'``)
1794
+
1795
+ EXAMPLES::
1796
+
1797
+ sage: from sage.misc.latex_standalone import TikzPicture
1798
+
1799
+ sage: # needs sage.graphs sage.modules
1800
+ sage: P = posets.PentagonPoset()
1801
+ sage: tikz = TikzPicture.from_poset(P) # optional - dot2tex graphviz
1802
+ doctest:...: FutureWarning: This class/method/function is marked as experimental.
1803
+ It, its functionality or its interface might change without a formal deprecation.
1804
+ See https://github.com/sagemath/sage/issues/20343 for details.
1805
+
1806
+ ::
1807
+
1808
+ sage: tikz = TikzPicture.from_poset(P, prog='neato', # long time (3s), optional - dot2tex, needs sage.graphs sage.modules
1809
+ ....: color_by_label=True)
1810
+
1811
+ ::
1812
+
1813
+ sage: # needs sage.graphs
1814
+ sage: P = posets.SymmetricGroupWeakOrderPoset(4)
1815
+ sage: tikz = TikzPicture.from_poset(P) # long time (4s), optional - dot2tex graphviz
1816
+ sage: tikz = TikzPicture.from_poset(P, prog='neato') # long time (4s), optional - dot2tex graphviz
1817
+ """
1818
+ graph = poset.hasse_diagram()
1819
+ return cls.from_graph(graph, **kwds)
1820
+
1821
+ def tikz_picture_code(self):
1822
+ r"""
1823
+ EXAMPLES::
1824
+
1825
+ sage: from sage.misc.latex_standalone import TikzPicture
1826
+ sage: s = "\\begin{tikzpicture}\n\\draw (0,0) -- (1,1);\n\\end{tikzpicture}"
1827
+ sage: t = TikzPicture(s)
1828
+ sage: print(t.tikz_picture_code())
1829
+ \begin{tikzpicture}
1830
+ \draw (0,0) -- (1,1);
1831
+ \end{tikzpicture}
1832
+ """
1833
+ return self.content()