iplotx 1.3.0__tar.gz → 1.4.1__tar.gz

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 (272) hide show
  1. {iplotx-1.3.0 → iplotx-1.4.1}/PKG-INFO +1 -1
  2. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/api/complete_style_specification.md +8 -3
  3. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/installing.md +9 -31
  4. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/sg_execution_times.rst +9 -3
  5. iplotx-1.4.1/gallery/basic/plot_arcs.py +47 -0
  6. iplotx-1.4.1/gallery/style/plot_edge_geometries.py +61 -0
  7. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/edge/__init__.py +8 -1
  8. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/edge/geometry.py +113 -0
  9. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/layout/tree/unrooted.py +118 -57
  10. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/style/leaf_info.py +1 -0
  11. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/version.py +1 -1
  12. iplotx-1.4.1/tests/baseline_images/test_igraph/arcs.png +0 -0
  13. iplotx-1.4.1/tests/baseline_images/test_igraph/directed_arcs.png +0 -0
  14. iplotx-1.4.1/tests/baseline_images/test_igraph/large_arcs.png +0 -0
  15. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_igraph.py +44 -0
  16. {iplotx-1.3.0 → iplotx-1.4.1}/.github/workflows/publish.yml +0 -0
  17. {iplotx-1.3.0 → iplotx-1.4.1}/.github/workflows/test.yml +0 -0
  18. {iplotx-1.3.0 → iplotx-1.4.1}/.gitignore +0 -0
  19. {iplotx-1.3.0 → iplotx-1.4.1}/.pre-commit-config.yaml +0 -0
  20. {iplotx-1.3.0 → iplotx-1.4.1}/.readthedocs.yaml +0 -0
  21. {iplotx-1.3.0 → iplotx-1.4.1}/LICENSE +0 -0
  22. {iplotx-1.3.0 → iplotx-1.4.1}/MANIFEST.in +0 -0
  23. {iplotx-1.3.0 → iplotx-1.4.1}/README.md +0 -0
  24. {iplotx-1.3.0 → iplotx-1.4.1}/assets/pylint.svg +0 -0
  25. {iplotx-1.3.0 → iplotx-1.4.1}/docs/Makefile +0 -0
  26. {iplotx-1.3.0 → iplotx-1.4.1}/docs/make.bat +0 -0
  27. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/_static/banner.png +0 -0
  28. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/_static/custom-icons.js +0 -0
  29. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/_static/custom.css +0 -0
  30. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/_static/graph_basic.png +0 -0
  31. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/_templates/layout.html +0 -0
  32. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/api/artists.md +0 -0
  33. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/api/plotting.md +0 -0
  34. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/api/providers.md +0 -0
  35. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/api/style.md +0 -0
  36. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/api.md +0 -0
  37. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/code_of_conduct.rst +0 -0
  38. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/conf.py +0 -0
  39. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/images/sphx_glr_plot_basic_001.png +0 -0
  40. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/images/thumb/sphx_glr_plot_basic_thumb.png +0 -0
  41. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/index.md +0 -0
  42. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/providers.md +0 -0
  43. {iplotx-1.3.0 → iplotx-1.4.1}/docs/source/style.md +0 -0
  44. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/GALLERY_HEADER.rst +0 -0
  45. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/basic/GALLERY_HEADER.rst +0 -0
  46. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/basic/plot_3d.py +0 -0
  47. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/basic/plot_basic.py +0 -0
  48. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/basic/plot_big_curves.py +0 -0
  49. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/basic/plot_dag.py +0 -0
  50. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/basic/plot_directed.py +0 -0
  51. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/basic/plot_grouping.py +0 -0
  52. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/basic/plot_house.py +0 -0
  53. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/basic/plot_loops.py +0 -0
  54. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/basic/plot_simple_path.py +0 -0
  55. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/GALLERY_HEADER.rst +0 -0
  56. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/data/80201010000000001.mst +0 -0
  57. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/data/GN-tree.json +0 -0
  58. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/data/breast_cancer_string_interactions_short.tsv +0 -0
  59. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/data/breast_cancer_string_network_coordinates.tsv +0 -0
  60. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/data/cell_cycle_arrest_string_interactions_short.tsv +0 -0
  61. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/data/cell_cycle_arrest_string_network_coordinates.tsv +0 -0
  62. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/data/fevo-08-588430_DataSheet1_S1.csv +0 -0
  63. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/plot_animal_phylogeny.py +0 -0
  64. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/plot_antibody_clone.py +0 -0
  65. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/plot_breast_cancer_ppi.py +0 -0
  66. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/plot_cell_cycle_arrest.py +0 -0
  67. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/plot_food_network.py +0 -0
  68. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/plot_foraging_table.py +0 -0
  69. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/plot_pollinators.py +0 -0
  70. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/plot_ppi.py +0 -0
  71. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/biology/plot_tca_cycle.py +0 -0
  72. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/GALLERY_HEADER.rst +0 -0
  73. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/data/chess_masters_WCC.pgn.bz2 +0 -0
  74. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/data/knuth_miles.txt.gz +0 -0
  75. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_arrowlawn.py +0 -0
  76. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_chess_masters.py +0 -0
  77. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_cliques.py +0 -0
  78. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_cluster_layout.py +0 -0
  79. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_company_structure.py +0 -0
  80. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_complex.py +0 -0
  81. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_financial_network.py +0 -0
  82. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_knuth_miles.py +0 -0
  83. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_labels_and_colors.py +0 -0
  84. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_max_bipartite_matching.py +0 -0
  85. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_minimum_spanning_trees.py +0 -0
  86. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_multipartite_layout.py +0 -0
  87. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_parallel_igraph_networkx.py +0 -0
  88. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_redblack.py +0 -0
  89. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_shortest_path.py +0 -0
  90. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_simple_networkx.py +0 -0
  91. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_social_network_circles.py +0 -0
  92. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_traveling_salesman.py +0 -0
  93. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/network_science/plot_with_colorbar.py +0 -0
  94. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/other/GALLERY_HEADER.rst +0 -0
  95. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/other/plot_animation.py +0 -0
  96. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/other/plot_edit_artists.py +0 -0
  97. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/other/plot_feedbacks.py +0 -0
  98. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/other/plot_graph.py +0 -0
  99. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/other/plot_mouse_hover.py +0 -0
  100. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/other/plot_train.py +0 -0
  101. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/GALLERY_HEADER.rst +0 -0
  102. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_arrows.py +0 -0
  103. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_depthshade.py +0 -0
  104. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_edgepadding.py +0 -0
  105. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_elements.py +0 -0
  106. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_four_grids.py +0 -0
  107. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_halfarrows.py +0 -0
  108. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_multistyle.py +0 -0
  109. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_ports.py +0 -0
  110. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_style.py +0 -0
  111. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_tension.py +0 -0
  112. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_vertexmarkers.py +0 -0
  113. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_voronoi.py +0 -0
  114. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/style/plot_waypoints.py +0 -0
  115. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/GALLERY_HEADER.rst +0 -0
  116. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/data/tree-with-support.json +0 -0
  117. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_angular_waypoints.py +0 -0
  118. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_biopython_tree.py +0 -0
  119. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_cladeedges.py +0 -0
  120. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_cogent3_layouts.py +0 -0
  121. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_cogent3_tree.py +0 -0
  122. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_dendropy.py +0 -0
  123. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_double_tree.py +0 -0
  124. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_elements_tree.py +0 -0
  125. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_equalangle.py +0 -0
  126. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_ete4.py +0 -0
  127. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_leafedges.py +0 -0
  128. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_leafedges_and_cascades.py +0 -0
  129. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_scalebar.py +0 -0
  130. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_skbio_tree.py +0 -0
  131. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_split_edges.py +0 -0
  132. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_style_tree.py +0 -0
  133. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_support.py +0 -0
  134. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_tree_node_background.py +0 -0
  135. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_tree_style_clades.py +0 -0
  136. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/tree/plot_trees_of_trees.py +0 -0
  137. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/zero_dependency/GALLERY_HEADER.rst +0 -0
  138. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/zero_dependency/plot_simplenetworkdataprovider.py +0 -0
  139. {iplotx-1.3.0 → iplotx-1.4.1}/gallery/zero_dependency/plot_simpletreedataprovider.py +0 -0
  140. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/__init__.py +0 -0
  141. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/art3d/edge/__init__.py +0 -0
  142. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/art3d/edge/arrow.py +0 -0
  143. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/art3d/edge/geometry.py +0 -0
  144. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/art3d/vertex.py +0 -0
  145. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/artists.py +0 -0
  146. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/edge/arrow.py +0 -0
  147. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/edge/leaf.py +0 -0
  148. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/edge/ports.py +0 -0
  149. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/__init__.py +0 -0
  150. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/heuristics.py +0 -0
  151. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/providers/network/graph_tool.py +0 -0
  152. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/providers/network/igraph.py +0 -0
  153. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/providers/network/networkx.py +0 -0
  154. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/providers/network/simple.py +0 -0
  155. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/providers/tree/biopython.py +0 -0
  156. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/providers/tree/cogent3.py +0 -0
  157. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/providers/tree/dendropy.py +0 -0
  158. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/providers/tree/ete4.py +0 -0
  159. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/providers/tree/simple.py +0 -0
  160. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/providers/tree/skbio.py +0 -0
  161. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/ingest/typing.py +0 -0
  162. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/label.py +0 -0
  163. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/layout/__init__.py +0 -0
  164. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/layout/tree/__init__.py +0 -0
  165. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/layout/tree/rooted.py +0 -0
  166. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/network/__init__.py +0 -0
  167. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/network/groups.py +0 -0
  168. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/plotting.py +0 -0
  169. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/style/__init__.py +0 -0
  170. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/style/library.py +0 -0
  171. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/tree/__init__.py +0 -0
  172. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/tree/cascades.py +0 -0
  173. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/tree/scalebar.py +0 -0
  174. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/typing.py +0 -0
  175. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/utils/geometry.py +0 -0
  176. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/utils/internal.py +0 -0
  177. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/utils/matplotlib.py +0 -0
  178. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/utils/style.py +0 -0
  179. {iplotx-1.3.0 → iplotx-1.4.1}/iplotx/vertex.py +0 -0
  180. {iplotx-1.3.0 → iplotx-1.4.1}/pyproject.toml +0 -0
  181. {iplotx-1.3.0 → iplotx-1.4.1}/scripts/copy_github_release_into_version.sh +0 -0
  182. {iplotx-1.3.0 → iplotx-1.4.1}/scripts/make_banner.py +0 -0
  183. {iplotx-1.3.0 → iplotx-1.4.1}/scripts/update_pylint_badge.sh +0 -0
  184. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_biopython/cascades.png +0 -0
  185. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_biopython/directed_child.png +0 -0
  186. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_biopython/leaf_labels.png +0 -0
  187. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_biopython/leaf_labels_hmargin.png +0 -0
  188. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_biopython/leafedges.png +0 -0
  189. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_biopython/show_support.png +0 -0
  190. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_biopython/tree_basic.png +0 -0
  191. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_biopython/tree_radial.png +0 -0
  192. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_cogent3/leaf_labels.png +0 -0
  193. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_cogent3/leaf_labels_hmargin.png +0 -0
  194. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_cogent3/tree_basic.png +0 -0
  195. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_cogent3/tree_radial.png +0 -0
  196. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_dendropy/cascades.png +0 -0
  197. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_dendropy/directed_child.png +0 -0
  198. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_dendropy/leaf_labels.png +0 -0
  199. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_dendropy/leaf_labels_hmargin.png +0 -0
  200. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_dendropy/leafedges.png +0 -0
  201. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_dendropy/tree_basic.png +0 -0
  202. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_dendropy/tree_radial.png +0 -0
  203. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_doubletree/tree_gap.png +0 -0
  204. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_doubletree/tree_nogap.png +0 -0
  205. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_ete4/equalangle_layout.png +0 -0
  206. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_ete4/leaf_labels.png +0 -0
  207. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_ete4/leaf_labels_hmargin.png +0 -0
  208. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_ete4/split_edges.png +0 -0
  209. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_ete4/tree_basic.png +0 -0
  210. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_ete4/tree_radial.png +0 -0
  211. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_graph_tool/graph_basic.png +0 -0
  212. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_graph_tool/graph_directed.png +0 -0
  213. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/clustering_directed.png +0 -0
  214. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/clustering_directed_large.png +0 -0
  215. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/graph_basic.png +0 -0
  216. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/graph_directed.png +0 -0
  217. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/graph_directed_curved_loops.png +0 -0
  218. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/graph_edit_children.png +0 -0
  219. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/graph_labels.png +0 -0
  220. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/graph_layout_attribute.png +0 -0
  221. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/graph_null.png +0 -0
  222. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/graph_squares_directed.png +0 -0
  223. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/graph_vertexsize.png +0 -0
  224. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/graph_with_curved_edges.png +0 -0
  225. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/igraph_layout_object.png +0 -0
  226. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph/multigraph_with_curved_edges_undirected.png +0 -0
  227. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph_3d/directed.png +0 -0
  228. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph_3d/undirected.png +0 -0
  229. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_igraph_3d/vertex_labels.png +0 -0
  230. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/cluster-layout.png +0 -0
  231. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/complex.png +0 -0
  232. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/complex_rotatelabels.png +0 -0
  233. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/directed_graph.png +0 -0
  234. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/directed_graph_with_colorbar.png +0 -0
  235. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/empty_graph.png +0 -0
  236. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/flat_style.png +0 -0
  237. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/house_with_colors.png +0 -0
  238. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/labels_and_colors.png +0 -0
  239. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/shortest_path.png +0 -0
  240. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_networkx/simple_graph.png +0 -0
  241. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_simple_network_provider/graph_basic.png +0 -0
  242. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_simple_network_provider/graph_directed.png +0 -0
  243. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_simple_network_provider/graph_labels.png +0 -0
  244. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_skbio/leaf_labels.png +0 -0
  245. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_skbio/leaf_labels_hmargin.png +0 -0
  246. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_skbio/tree_basic.png +0 -0
  247. {iplotx-1.3.0 → iplotx-1.4.1}/tests/baseline_images/test_skbio/tree_radial.png +0 -0
  248. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_arrows.py +0 -0
  249. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_biopython.py +0 -0
  250. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_cascades.py +0 -0
  251. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_cogent3.py +0 -0
  252. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_dendropy.py +0 -0
  253. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_doubletree.py +0 -0
  254. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_edge.py +0 -0
  255. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_edge_geometry.py +0 -0
  256. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_ete4.py +0 -0
  257. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_geometry.py +0 -0
  258. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_graph_tool.py +0 -0
  259. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_heuristics.py +0 -0
  260. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_igraph_3d.py +0 -0
  261. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_ingest_protocols.py +0 -0
  262. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_matplotlib_utils.py +0 -0
  263. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_network_hotload.py +0 -0
  264. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_networkx.py +0 -0
  265. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_ports.py +0 -0
  266. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_simple_network_provider.py +0 -0
  267. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_simple_tree_provider.py +0 -0
  268. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_skbio.py +0 -0
  269. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_style.py +0 -0
  270. {iplotx-1.3.0 → iplotx-1.4.1}/tests/test_vertex.py +0 -0
  271. {iplotx-1.3.0 → iplotx-1.4.1}/tests/utils.py +0 -0
  272. {iplotx-1.3.0 → iplotx-1.4.1}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iplotx
3
- Version: 1.3.0
3
+ Version: 1.4.1
4
4
  Summary: Plot networkx from igraph and networkx.
5
5
  Project-URL: Homepage, https://github.com/fabilab/iplotx
6
6
  Project-URL: Documentation, https://readthedocs.org/iplotx
@@ -102,9 +102,14 @@
102
102
 
103
103
  "curved": bool, # Whether the edge is curved (True) or straight (False)
104
104
 
105
- # Tension for curved edges (0.0 for straight, higher values position the
106
- # Bezier control points further away from the nodes, creating more wiggly lines)
105
+ # Tension for curved edges and arcs.
106
+ # For Bezier (curved) edges, 0.0 means straight, higher values position the
107
+ # Bezier control points further away from the nodes, creating more wiggly lines.
107
108
  # Negative values bend the curve on the other side of the straight line.
109
+ # For arc edges, 0.0 means straight, higher values draw larger arcs. 1.0
110
+ # means a semicircle, and numbers above 5 create very large arcs, almost full
111
+ # circles. The exact definition of tension for arcs is the tangent of a
112
+ # quarter of the angle spanned by the arc.
108
113
  "tension": float,
109
114
 
110
115
  # Tension for self-loops (higher values create more bigger loops).
@@ -281,7 +286,7 @@
281
286
  # For horizontal and vertical layouts:
282
287
  # start: Starting position in data units (tuple of two floats)
283
288
  # span: Breadth in data units (float)
284
- "start": float | tuple[float, float],
289
+ "start": float | tuple[float margins=0.2,
285
290
  "span": float,
286
291
  },
287
292
  ############################################################################
@@ -11,13 +11,11 @@ pip install iplotx
11
11
 
12
12
  ```
13
13
  import igraph as ig
14
- import matplotlib.pyplot as plt
15
14
  import iplotx as ipx
16
15
 
17
16
  g = ig.Graph.Ring(5)
18
17
  layout = g.layout("circle").coords
19
- fig, ax = plt.subplots(figsize=(3, 3))
20
- ipx.plot(g, ax=ax, layout=layout)
18
+ ipx.network(g, layout)
21
19
  ```
22
20
 
23
21
 
@@ -27,13 +25,11 @@ ipx.plot(g, ax=ax, layout=layout)
27
25
  :::{tab-item} networkx
28
26
  ```
29
27
  import networkx as nx
30
- import matplotlib.pyplot as plt
31
28
  import iplotx as ipx
32
29
 
33
30
  g = nx.Graph([(0, 1), (1, 2), (2, 3), (3, 4), (4, 0)])
34
31
  layout = nx.layout.circular_layout(g)
35
- fig, ax = plt.subplots(figsize=(3, 3))
36
- ipx.plot(g, ax=ax, layout=layout)
32
+ ipx.network(g, layout)
37
33
  ```
38
34
 
39
35
  :::
@@ -44,9 +40,6 @@ Either way, the result is the same:
44
40
 
45
41
  ![graph_basic](_static/graph_basic.png)
46
42
 
47
- ## Gallery
48
- See <project:gallery/index.rst> for examples of plots made with `iplotx`. Feel free to suggest new examples on GitHub by opening a new issue or pull request!
49
-
50
43
  ## Features
51
44
  `iplotx`'s features' include:
52
45
  - per-edge and per-vertex styling using sequences or dictionaries
@@ -72,32 +65,17 @@ See <project:gallery/index.rst> for examples of plots made with `iplotx`. Feel f
72
65
  - animations (see <project:gallery/other/plot_animation.rst>)
73
66
  - 3D visualisations
74
67
  - mouse/keyboard interaction and events (e.g. hover, click, see <project:gallery/other/plot_mouse_hover.rst>)
75
- - ... and probably more by the time you read this.
68
+ - ... and many more.
76
69
 
77
- ## Styles
78
- `iplotx` is designed to produce publication-quality figures using **styles**, which are dictionaries specifying the visual properties of each graph element, including vertices, edges, arrows, labels, and groupings.
70
+ ## Rationale
71
+ We believe graph **analysis**, graph **layouting**, and graph **visualisation** to be three separate tasks. `iplotx` currently focuses on visualisation. It can also compute simple tree layouts and might expand towards network layouts in the future.
79
72
 
80
- An example of style specification is as follows:
73
+ ## Citation
74
+ If you use `iplotx` for publication figures, please cite the [zenodo preprint](https://doi.org/10.5281/zenodo.16599333):
81
75
 
82
- ```python
83
- import iplotx as ipx
84
- with ipx.style.context({
85
- 'vertex': {
86
- 'size': 30,
87
- 'facecolor': 'red',
88
- 'edgecolor': 'none',
89
- }
90
- }):
91
- ipx.plot(...)
92
76
  ```
93
-
94
- See <project:style.md> for more info.
95
-
96
- ## Reference API
97
- See <project:api.md> for reference documentation of all functions and classes in `iplotx`.
98
-
99
- ## Rationale
100
- We believe graph **analysis**, graph **layouting**, and graph **visualisation** to be three separate tasks. `iplotx` currently focuses on visualisation. It can also compute simple tree layouts and might expand towards network layouts in the future.
77
+ F. Zanini. (2025). Unified network visualisation in Python. Zenodo [PREPRINT]. https://doi.org/10.5281/zenodo.16599333
78
+ ```
101
79
 
102
80
  ## Contributing
103
81
  Open an [issue on GitHub](https://github.com/fabilab/iplotx/issues) to request features, report bugs, or show intention in contributing. Pull requests are very welcome.
@@ -6,7 +6,7 @@
6
6
 
7
7
  Computation times
8
8
  =================
9
- **00:00.514** total execution time for 78 files **from all galleries**:
9
+ **00:00.158** total execution time for 80 files **from all galleries**:
10
10
 
11
11
  .. container::
12
12
 
@@ -32,12 +32,15 @@ Computation times
32
32
  * - Example
33
33
  - Time
34
34
  - Mem (MB)
35
- * - :ref:`sphx_glr_gallery_tree_plot_equalangle.py` (``../../gallery/tree/plot_equalangle.py``)
36
- - 00:00.514
35
+ * - :ref:`sphx_glr_gallery_style_plot_edge_geometries.py` (``../../gallery/style/plot_edge_geometries.py``)
36
+ - 00:00.158
37
37
  - 0.0
38
38
  * - :ref:`sphx_glr_gallery_basic_plot_3d.py` (``../../gallery/basic/plot_3d.py``)
39
39
  - 00:00.000
40
40
  - 0.0
41
+ * - :ref:`sphx_glr_gallery_basic_plot_arcs.py` (``../../gallery/basic/plot_arcs.py``)
42
+ - 00:00.000
43
+ - 0.0
41
44
  * - :ref:`sphx_glr_gallery_basic_plot_basic.py` (``../../gallery/basic/plot_basic.py``)
42
45
  - 00:00.000
43
46
  - 0.0
@@ -227,6 +230,9 @@ Computation times
227
230
  * - :ref:`sphx_glr_gallery_tree_plot_elements_tree.py` (``../../gallery/tree/plot_elements_tree.py``)
228
231
  - 00:00.000
229
232
  - 0.0
233
+ * - :ref:`sphx_glr_gallery_tree_plot_equalangle.py` (``../../gallery/tree/plot_equalangle.py``)
234
+ - 00:00.000
235
+ - 0.0
230
236
  * - :ref:`sphx_glr_gallery_tree_plot_ete4.py` (``../../gallery/tree/plot_ete4.py``)
231
237
  - 00:00.000
232
238
  - 0.0
@@ -0,0 +1,47 @@
1
+ """
2
+ Arcs
3
+ ====
4
+
5
+ This example showcases the ability of `iplotx` to curve edges into arcs, using tension to define the angular span of the arc.
6
+ """
7
+
8
+ import igraph as ig
9
+ import matplotlib.pyplot as plt
10
+ import iplotx as ipx
11
+
12
+
13
+ g = ig.Graph.Full(4)
14
+ layout = [[0, 0], [1, 0], [2, 0], [3, 0]]
15
+
16
+ fig, ax = plt.subplots()
17
+ ipx.plot(
18
+ g,
19
+ layout=layout,
20
+ ax=ax,
21
+ edge_arc=True,
22
+ edge_tension=-1,
23
+ )
24
+
25
+ # %%
26
+ #
27
+ # Other values of tension can be used to create different arc shapes:
28
+
29
+ fig, axs = plt.subplots(2, 2, figsize=(8, 8))
30
+ for tension, ax in zip([0.5, 2.5, -0.5, -2.5], axs.ravel()):
31
+ ipx.plot(
32
+ g,
33
+ layout=layout,
34
+ ax=ax,
35
+ edge_arc=True,
36
+ edge_tension=tension,
37
+ margins=0.15,
38
+ title=f"Edge tension = {tension:.2f}",
39
+ )
40
+
41
+ # %%
42
+ # .. tip::
43
+ # Tension is defined as the tangent of the quarter of the angle spanned by the arc. A tension of 0 gives
44
+ # a straight line, a tension of 1 gives a semicircle, and higher tensions give increasingly larger arcs. A tension of
45
+ # infinity would give you a straight line away from the target vertex, but is not accepted by the library. Negative
46
+ # tensions result in arcs curving in the opposite direction.
47
+ #
@@ -0,0 +1,61 @@
1
+ """
2
+ Edge geometries
3
+ ===============
4
+
5
+ This example shows how to use edge geometries and tension to achieve different visualisation styles.
6
+ """
7
+
8
+
9
+ import igraph as ig
10
+ import matplotlib.pyplot as plt
11
+ import iplotx as ipx
12
+
13
+
14
+ g = ig.Graph.Full(2)
15
+ layout = [[0, 0], [1, 0]]
16
+
17
+ fig, axs = plt.subplots(3, 3, figsize=(6, 6), sharex=True, sharey=True)
18
+ tensions = [
19
+ [1, 5, 10],
20
+ [0.2, 1, 2],
21
+ ]
22
+ for edge_arc, axrow, tensionrow in zip([False, True], axs, tensions):
23
+ kwargs = {}
24
+ if not edge_arc:
25
+ kwargs["edge_curved"] = True
26
+ for tension, ax in zip(tensionrow, axrow):
27
+ ipx.plot(
28
+ g,
29
+ layout=layout,
30
+ ax=ax,
31
+ edge_arc=edge_arc,
32
+ edge_tension=tension,
33
+ title=f"Tension {tension:.1f}",
34
+ node_size=10,
35
+ **kwargs,
36
+ )
37
+ axs[0, 0].set_ylabel("Bezier", fontsize=12)
38
+ axs[1, 0].set_ylabel("Arc", fontsize=12)
39
+ ipx.plot(
40
+ g,
41
+ layout,
42
+ ax=axs[2, 0],
43
+ node_size=10,
44
+ )
45
+ axs[2, 0].set_ylabel("Straight", fontsize=12)
46
+ ipx.plot(
47
+ g,
48
+ layout,
49
+ ax=axs[2, 1],
50
+ node_size=10,
51
+ edge_waypoints=[[0.5, -0.15]],
52
+ )
53
+ ipx.plot(
54
+ g,
55
+ layout,
56
+ ax=axs[2, 2],
57
+ node_size=10,
58
+ edge_waypoints=[[[0.25, -0.15], [0.75, -0.15]]],
59
+ )
60
+ axs[2, 1].set_ylabel("Waypoints", fontsize=12)
61
+ fig.tight_layout()
@@ -370,6 +370,9 @@ class EdgeCollection(mpl.collections.PatchCollection):
370
370
  if edge_stylei.get("curved", False):
371
371
  tension = edge_stylei.get("tension", 5)
372
372
  ports = edge_stylei.get("ports", (None, None))
373
+ elif edge_stylei.get("arc", False):
374
+ tension = edge_stylei.get("tension", 1)
375
+ ports = None
373
376
  else:
374
377
  tension = 0
375
378
  ports = None
@@ -391,6 +394,8 @@ class EdgeCollection(mpl.collections.PatchCollection):
391
394
  if waypoints != "none":
392
395
  ports = edge_stylei.get("ports", (None, None))
393
396
 
397
+ arc = edge_stylei.get("arc", False)
398
+
394
399
  # Compute actual edge path
395
400
  path, angles = _compute_edge_path(
396
401
  vcoord_data,
@@ -401,6 +406,7 @@ class EdgeCollection(mpl.collections.PatchCollection):
401
406
  tension=tension,
402
407
  waypoints=waypoints,
403
408
  ports=ports,
409
+ arc=arc,
404
410
  layout_coordinate_system=self._vertex_collection.get_layout_coordinate_system(),
405
411
  shrink=shrink,
406
412
  )
@@ -447,7 +453,7 @@ class EdgeCollection(mpl.collections.PatchCollection):
447
453
  # If none found, empty the dictionary already
448
454
  if (len(parallel_edges) == 0) or (max(parallel_edges.values(), key=len) == 1):
449
455
  parallel_edges = {}
450
- if not self._style.get("curved", False):
456
+ if (not self._style.get("curved", False)) and (not self._style.get("arc", False)):
451
457
  while len(parallel_edges) > 0:
452
458
  (v1, v2), indices = parallel_edges.popitem()
453
459
  indices_inv = parallel_edges.pop((v2, v1), [])
@@ -712,6 +718,7 @@ def make_stub_patch(**kwargs):
712
718
  "split",
713
719
  "shrink",
714
720
  "depthshade",
721
+ "arc",
715
722
  # DEPRECATED
716
723
  "padding",
717
724
  ]
@@ -393,6 +393,108 @@ def _compute_edge_path_waypoints(
393
393
  return path, angles
394
394
 
395
395
 
396
+ def _compute_edge_path_arc(
397
+ tension,
398
+ vcoord_data,
399
+ vpath_fig,
400
+ vsize_fig,
401
+ trans,
402
+ trans_inv,
403
+ ports: Pair[Optional[str]] = (None, None),
404
+ shrink: float = 0,
405
+ ):
406
+ """Shorten the edge path along an arc.
407
+
408
+ Parameters:
409
+ tension: the tension of the arc. This is defined, for this function, as the tangent
410
+ of the angle spanning the arc. For instance, for a semicircle, the angle is
411
+ 180 degrees, so the tension is +-1 (depending on the orientation).
412
+ """
413
+
414
+ # Coordinates in figure (default) coords
415
+ vcoord_fig = trans(vcoord_data)
416
+
417
+ dv = vcoord_fig[1] - vcoord_fig[0]
418
+
419
+ # Tension is the fraction of the semicircle covered by the
420
+ # arc. Values are clipped between -1 (left-hand semicircle)
421
+ # and 1 (right-hand semicircle). 0 means a straight line,
422
+ # which is a (degenerate) arc too.
423
+ if tension == 0:
424
+ vs = [None, None]
425
+ thetas = [atan2(dv[1], dv[0])]
426
+ thetas.append(-thetas[0])
427
+ for i in range(2):
428
+ vs[i] = (
429
+ _get_shorter_edge_coords(vpath_fig[i], vsize_fig[i], thetas[i], shrink)
430
+ + vcoord_fig[i]
431
+ )
432
+ auxs = []
433
+
434
+ else:
435
+ edge_straight_length = np.sqrt((dv**2).sum())
436
+ theta_straight = atan2(dv[1], dv[0])
437
+ theta_tension = 4 * np.arctan(tension)
438
+ # print(f"theta_straight: {np.degrees(theta_straight):.2f}")
439
+ # print(f"theta_tension: {np.degrees(theta_tension):.2f}")
440
+ # NOTE: positive tension means an arc shooting off to the right of the straight
441
+ # line, same convensio as for tension elsewhere in the codebase.
442
+ thetas = [theta_straight - theta_tension / 2, np.pi + theta_straight + theta_tension / 2]
443
+ # This is guaranteed to be finite because tension == 0 is taken care of above,
444
+ # and tension = np.inf is not allowed.
445
+ mid = vcoord_fig.mean(axis=0)
446
+ # print(f"theta_s: {thetas}")
447
+ # print(f"mid: {mid}")
448
+ theta_offset = theta_straight + np.pi / 2
449
+ if np.abs(tension) <= 1:
450
+ offset_length = edge_straight_length / 2 / np.tan(theta_tension / 2)
451
+ else:
452
+ # print("Large tension arc")
453
+ offset_length = -edge_straight_length / 2 * np.tan(theta_tension / 2 - np.pi / 2)
454
+ # print(f"theta_offset: {np.degrees(theta_offset):.2f}")
455
+ offset = offset_length * np.array([np.cos(theta_offset), np.sin(theta_offset)])
456
+ # print(f"offset: {offset}")
457
+ center = mid + offset
458
+ # print(f"center: {center}")
459
+
460
+ # Compute shorter start and end points
461
+ vs = [None, None]
462
+ for i in range(2):
463
+ vs[i] = (
464
+ _get_shorter_edge_coords(vpath_fig[i], vsize_fig[i], thetas[i], shrink)
465
+ + vcoord_fig[i]
466
+ )
467
+ angle_start = atan2(*(vs[0] - center)[::-1])
468
+ angle_end = atan2(*(vs[1] - center)[::-1])
469
+ if (np.abs(tension) > 1) and (np.abs(angle_end - angle_start) < np.pi):
470
+ if angle_end > angle_start:
471
+ angle_start += 2 * np.pi
472
+ else:
473
+ angle_end += 2 * np.pi
474
+ # print(f"angle_start: {np.degrees(angle_start):.2f}")
475
+ # print(f"angle_end: {np.degrees(angle_end):.2f}")
476
+
477
+ naux = 30
478
+ angles = np.linspace(angle_start, angle_end, naux + 2)[1:-1]
479
+ auxs = center + np.array([np.cos(angles), np.sin(angles)]).T * np.linalg.norm(
480
+ vs[0] - center
481
+ )
482
+
483
+ path = {
484
+ "vertices": [vs[0]] + list(auxs) + [vs[1]],
485
+ "codes": ["MOVETO"] + ["LINETO"] * (len(auxs) + 1),
486
+ }
487
+
488
+ path = mpl.path.Path(
489
+ path["vertices"],
490
+ codes=[getattr(mpl.path.Path, x) for x in path["codes"]],
491
+ )
492
+
493
+ # Return to data transform
494
+ path.vertices = trans_inv(path.vertices)
495
+ return path, tuple(thetas)
496
+
497
+
396
498
  def _compute_edge_path_curved(
397
499
  tension,
398
500
  vcoord_data,
@@ -483,12 +585,15 @@ def _compute_edge_path(
483
585
  tension: float = 0,
484
586
  waypoints: str | tuple[float, float] | Sequence[tuple[float, float]] | np.ndarray = "none",
485
587
  ports: Pair[Optional[str]] = (None, None),
588
+ arc: bool = False,
486
589
  layout_coordinate_system: str = "cartesian",
487
590
  **kwargs,
488
591
  ):
489
592
  """Compute the edge path in a few different ways."""
490
593
  if (waypoints != "none") and (tension != 0):
491
594
  raise ValueError("Waypoints not supported for curved edges.")
595
+ if (waypoints != "none") and arc:
596
+ raise ValueError("Waypoint not supported for arc edges.")
492
597
 
493
598
  if waypoints != "none":
494
599
  return _compute_edge_path_waypoints(
@@ -506,6 +611,14 @@ def _compute_edge_path(
506
611
  **kwargs,
507
612
  )
508
613
 
614
+ if arc:
615
+ return _compute_edge_path_arc(
616
+ tension,
617
+ *args,
618
+ ports=ports,
619
+ **kwargs,
620
+ )
621
+
509
622
  return _compute_edge_path_curved(
510
623
  tension,
511
624
  *args,