iplotx 1.2.1__tar.gz → 1.3.0__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.
- {iplotx-1.2.1 → iplotx-1.3.0}/PKG-INFO +11 -4
- {iplotx-1.2.1 → iplotx-1.3.0}/README.md +10 -3
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/code_of_conduct.rst +1 -1
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/sg_execution_times.rst +6 -3
- iplotx-1.3.0/gallery/tree/plot_equalangle.py +35 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/providers/tree/biopython.py +2 -1
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/providers/tree/cogent3.py +4 -1
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/providers/tree/dendropy.py +10 -1
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/providers/tree/ete4.py +2 -1
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/providers/tree/simple.py +11 -1
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/providers/tree/skbio.py +4 -1
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/typing.py +49 -7
- iplotx-1.3.0/iplotx/layout/__init__.py +9 -0
- iplotx-1.3.0/iplotx/layout/tree/__init__.py +72 -0
- iplotx-1.2.1/iplotx/layout.py → iplotx-1.3.0/iplotx/layout/tree/rooted.py +3 -45
- iplotx-1.3.0/iplotx/layout/tree/unrooted.py +383 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/tree/__init__.py +5 -2
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/version.py +1 -1
- iplotx-1.3.0/tests/baseline_images/test_biopython/leafedges.png +0 -0
- iplotx-1.3.0/tests/baseline_images/test_biopython/tree_radial.png +0 -0
- iplotx-1.3.0/tests/baseline_images/test_cogent3/tree_radial.png +0 -0
- iplotx-1.3.0/tests/baseline_images/test_ete4/equalangle_layout.png +0 -0
- iplotx-1.3.0/tests/baseline_images/test_ete4/tree_radial.png +0 -0
- iplotx-1.3.0/tests/baseline_images/test_skbio/tree_radial.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_ete4.py +22 -4
- iplotx-1.2.1/tests/baseline_images/test_biopython/leafedges.png +0 -0
- iplotx-1.2.1/tests/baseline_images/test_biopython/tree_radial.png +0 -0
- iplotx-1.2.1/tests/baseline_images/test_cogent3/tree_radial.png +0 -0
- iplotx-1.2.1/tests/baseline_images/test_ete4/tree_radial.png +0 -0
- iplotx-1.2.1/tests/baseline_images/test_skbio/tree_radial.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/.github/workflows/publish.yml +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/.github/workflows/test.yml +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/.gitignore +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/.pre-commit-config.yaml +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/.readthedocs.yaml +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/LICENSE +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/MANIFEST.in +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/assets/pylint.svg +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/Makefile +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/make.bat +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/_static/banner.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/_static/custom-icons.js +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/_static/custom.css +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/_static/graph_basic.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/_templates/layout.html +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/api/artists.md +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/api/complete_style_specification.md +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/api/plotting.md +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/api/providers.md +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/api/style.md +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/api.md +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/conf.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/images/sphx_glr_plot_basic_001.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/images/thumb/sphx_glr_plot_basic_thumb.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/index.md +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/installing.md +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/providers.md +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/docs/source/style.md +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/basic/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/basic/plot_3d.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/basic/plot_basic.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/basic/plot_big_curves.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/basic/plot_dag.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/basic/plot_directed.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/basic/plot_grouping.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/basic/plot_house.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/basic/plot_loops.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/basic/plot_simple_path.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/data/80201010000000001.mst +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/data/GN-tree.json +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/data/breast_cancer_string_interactions_short.tsv +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/data/breast_cancer_string_network_coordinates.tsv +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/data/cell_cycle_arrest_string_interactions_short.tsv +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/data/cell_cycle_arrest_string_network_coordinates.tsv +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/data/fevo-08-588430_DataSheet1_S1.csv +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/plot_animal_phylogeny.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/plot_antibody_clone.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/plot_breast_cancer_ppi.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/plot_cell_cycle_arrest.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/plot_food_network.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/plot_foraging_table.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/plot_pollinators.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/plot_ppi.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/biology/plot_tca_cycle.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/data/chess_masters_WCC.pgn.bz2 +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/data/knuth_miles.txt.gz +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_arrowlawn.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_chess_masters.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_cliques.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_cluster_layout.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_company_structure.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_complex.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_financial_network.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_knuth_miles.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_labels_and_colors.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_max_bipartite_matching.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_minimum_spanning_trees.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_multipartite_layout.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_parallel_igraph_networkx.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_redblack.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_shortest_path.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_simple_networkx.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_social_network_circles.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_traveling_salesman.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/network_science/plot_with_colorbar.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/other/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/other/plot_animation.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/other/plot_edit_artists.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/other/plot_feedbacks.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/other/plot_graph.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/other/plot_mouse_hover.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/other/plot_train.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_arrows.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_depthshade.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_edgepadding.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_elements.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_four_grids.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_halfarrows.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_multistyle.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_ports.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_style.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_tension.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_vertexmarkers.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_voronoi.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/style/plot_waypoints.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/data/tree-with-support.json +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_angular_waypoints.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_biopython_tree.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_cladeedges.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_cogent3_layouts.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_cogent3_tree.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_dendropy.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_double_tree.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_elements_tree.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_ete4.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_leafedges.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_leafedges_and_cascades.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_scalebar.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_skbio_tree.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_split_edges.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_style_tree.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_support.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_tree_node_background.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_tree_style_clades.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/tree/plot_trees_of_trees.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/zero_dependency/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/zero_dependency/plot_simplenetworkdataprovider.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/gallery/zero_dependency/plot_simpletreedataprovider.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/__init__.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/art3d/edge/__init__.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/art3d/edge/arrow.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/art3d/edge/geometry.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/art3d/vertex.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/artists.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/edge/__init__.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/edge/arrow.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/edge/geometry.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/edge/leaf.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/edge/ports.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/__init__.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/heuristics.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/providers/network/graph_tool.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/providers/network/igraph.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/providers/network/networkx.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/ingest/providers/network/simple.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/label.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/network/__init__.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/network/groups.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/plotting.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/style/__init__.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/style/leaf_info.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/style/library.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/tree/cascades.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/tree/scalebar.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/typing.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/utils/geometry.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/utils/internal.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/utils/matplotlib.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/utils/style.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/iplotx/vertex.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/pyproject.toml +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/scripts/copy_github_release_into_version.sh +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/scripts/make_banner.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/scripts/update_pylint_badge.sh +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_biopython/cascades.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_biopython/directed_child.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_biopython/leaf_labels.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_biopython/leaf_labels_hmargin.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_biopython/show_support.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_biopython/tree_basic.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_cogent3/leaf_labels.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_cogent3/leaf_labels_hmargin.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_cogent3/tree_basic.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/cascades.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/directed_child.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/leaf_labels.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/leaf_labels_hmargin.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/leafedges.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/tree_basic.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/tree_radial.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_doubletree/tree_gap.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_doubletree/tree_nogap.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_ete4/leaf_labels.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_ete4/leaf_labels_hmargin.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_ete4/split_edges.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_ete4/tree_basic.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_graph_tool/graph_basic.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_graph_tool/graph_directed.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/clustering_directed.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/clustering_directed_large.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_basic.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_directed.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_directed_curved_loops.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_edit_children.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_labels.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_layout_attribute.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_null.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_squares_directed.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_vertexsize.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_with_curved_edges.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/igraph_layout_object.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph/multigraph_with_curved_edges_undirected.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph_3d/directed.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph_3d/undirected.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_igraph_3d/vertex_labels.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/cluster-layout.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/complex.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/complex_rotatelabels.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/directed_graph.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/directed_graph_with_colorbar.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/empty_graph.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/flat_style.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/house_with_colors.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/labels_and_colors.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/shortest_path.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_networkx/simple_graph.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_simple_network_provider/graph_basic.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_simple_network_provider/graph_directed.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_simple_network_provider/graph_labels.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_skbio/leaf_labels.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_skbio/leaf_labels_hmargin.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/baseline_images/test_skbio/tree_basic.png +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_arrows.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_biopython.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_cascades.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_cogent3.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_dendropy.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_doubletree.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_edge.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_edge_geometry.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_geometry.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_graph_tool.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_heuristics.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_igraph.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_igraph_3d.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_ingest_protocols.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_matplotlib_utils.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_network_hotload.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_networkx.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_ports.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_simple_network_provider.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_simple_tree_provider.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_skbio.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_style.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/test_vertex.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/tests/utils.py +0 -0
- {iplotx-1.2.1 → iplotx-1.3.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iplotx
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
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
|
|
@@ -36,9 +36,9 @@ Provides-Extra: networkx
|
|
|
36
36
|
Requires-Dist: networkx>=2.0.0; extra == 'networkx'
|
|
37
37
|
Description-Content-Type: text/markdown
|
|
38
38
|
|
|
39
|
-

|
|
40
|
-

|
|
41
|
-

|
|
39
|
+
[](https://github.com/fabilab/iplotx/actions/workflows/test.yml)
|
|
40
|
+
[](https://pypi.org/project/iplotx/)
|
|
41
|
+
[](https://iplotx.readthedocs.io/en/latest/)
|
|
42
42
|
[](https://coveralls.io/github/fabilab/iplotx?branch=main)
|
|
43
43
|

|
|
44
44
|
[](https://doi.org/10.5281/zenodo.16599333)
|
|
@@ -89,6 +89,13 @@ See [readthedocs](https://iplotx.readthedocs.io/en/latest/) for the full documen
|
|
|
89
89
|
## Gallery
|
|
90
90
|
See [gallery](https://iplotx.readthedocs.io/en/latest/gallery/index.html).
|
|
91
91
|
|
|
92
|
+
## Citation
|
|
93
|
+
If you use `iplotx` for publication figures, please cite the [zenodo preprint](https://doi.org/10.5281/zenodo.16599333):
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
F. Zanini. (2025). Unified network visualisation in Python. Zenodo [PREPRINT]. https://doi.org/10.5281/zenodo.16599333
|
|
97
|
+
```
|
|
98
|
+
|
|
92
99
|
## Features
|
|
93
100
|
- Plot networks from multiple libraries including networkx, igraph and graph-tool, using Matplotlib. ✅
|
|
94
101
|
- Plot trees from multiple libraries such as cogent3, ETE4, skbio, biopython, and dendropy. ✅
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-

|
|
2
|
-

|
|
3
|
-

|
|
1
|
+
[](https://github.com/fabilab/iplotx/actions/workflows/test.yml)
|
|
2
|
+
[](https://pypi.org/project/iplotx/)
|
|
3
|
+
[](https://iplotx.readthedocs.io/en/latest/)
|
|
4
4
|
[](https://coveralls.io/github/fabilab/iplotx?branch=main)
|
|
5
5
|

|
|
6
6
|
[](https://doi.org/10.5281/zenodo.16599333)
|
|
@@ -51,6 +51,13 @@ See [readthedocs](https://iplotx.readthedocs.io/en/latest/) for the full documen
|
|
|
51
51
|
## Gallery
|
|
52
52
|
See [gallery](https://iplotx.readthedocs.io/en/latest/gallery/index.html).
|
|
53
53
|
|
|
54
|
+
## Citation
|
|
55
|
+
If you use `iplotx` for publication figures, please cite the [zenodo preprint](https://doi.org/10.5281/zenodo.16599333):
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
F. Zanini. (2025). Unified network visualisation in Python. Zenodo [PREPRINT]. https://doi.org/10.5281/zenodo.16599333
|
|
59
|
+
```
|
|
60
|
+
|
|
54
61
|
## Features
|
|
55
62
|
- Plot networks from multiple libraries including networkx, igraph and graph-tool, using Matplotlib. ✅
|
|
56
63
|
- Plot trees from multiple libraries such as cogent3, ETE4, skbio, biopython, and dendropy. ✅
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Computation times
|
|
8
8
|
=================
|
|
9
|
-
**00:00.
|
|
9
|
+
**00:00.514** total execution time for 78 files **from all galleries**:
|
|
10
10
|
|
|
11
11
|
.. container::
|
|
12
12
|
|
|
@@ -32,8 +32,8 @@ Computation times
|
|
|
32
32
|
* - Example
|
|
33
33
|
- Time
|
|
34
34
|
- Mem (MB)
|
|
35
|
-
* - :ref:`
|
|
36
|
-
- 00:00.
|
|
35
|
+
* - :ref:`sphx_glr_gallery_tree_plot_equalangle.py` (``../../gallery/tree/plot_equalangle.py``)
|
|
36
|
+
- 00:00.514
|
|
37
37
|
- 0.0
|
|
38
38
|
* - :ref:`sphx_glr_gallery_basic_plot_3d.py` (``../../gallery/basic/plot_3d.py``)
|
|
39
39
|
- 00:00.000
|
|
@@ -221,6 +221,9 @@ Computation times
|
|
|
221
221
|
* - :ref:`sphx_glr_gallery_tree_plot_dendropy.py` (``../../gallery/tree/plot_dendropy.py``)
|
|
222
222
|
- 00:00.000
|
|
223
223
|
- 0.0
|
|
224
|
+
* - :ref:`sphx_glr_gallery_tree_plot_double_tree.py` (``../../gallery/tree/plot_double_tree.py``)
|
|
225
|
+
- 00:00.000
|
|
226
|
+
- 0.0
|
|
224
227
|
* - :ref:`sphx_glr_gallery_tree_plot_elements_tree.py` (``../../gallery/tree/plot_elements_tree.py``)
|
|
225
228
|
- 00:00.000
|
|
226
229
|
- 0.0
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Equal angle layout
|
|
3
|
+
==================
|
|
4
|
+
|
|
5
|
+
This example showcases the "equal angle" layout. This layout is inspired by the `ggtree <https://yulab-smu.top/treedata-book/chapter4.html>`_ layout with the same name, which originally comes from Joseph Felsenstein's book "Inferring Phylogenies".
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from cogent3.phylo import nj
|
|
9
|
+
import numpy as np
|
|
10
|
+
import iplotx as ipx
|
|
11
|
+
import matplotlib.pyplot as plt
|
|
12
|
+
|
|
13
|
+
nleaves = 14
|
|
14
|
+
distance_dict = {}
|
|
15
|
+
for i in range(nleaves):
|
|
16
|
+
for j in range(i):
|
|
17
|
+
distance_dict[(str(i), str(j))] = np.random.rand()
|
|
18
|
+
tree = nj.nj(distance_dict)
|
|
19
|
+
|
|
20
|
+
ipx.plotting.tree(
|
|
21
|
+
tree,
|
|
22
|
+
layout="equalangle",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# %%
|
|
27
|
+
# The "equal daylight" layout is an adjustment of the equal angle layout that attempts to spread out leaves more evenly
|
|
28
|
+
# for imbalanced trees. ``iplotx`` has an experimental implementation of this layout.
|
|
29
|
+
#
|
|
30
|
+
# .. warning:: "Experimental" means you can use it but the API and resulting layout may change in future releases.
|
|
31
|
+
|
|
32
|
+
ipx.plotting.tree(
|
|
33
|
+
tree,
|
|
34
|
+
layout="daylight",
|
|
35
|
+
)
|
|
@@ -21,8 +21,9 @@ class BiopythonDataProvider(TreeDataProvider):
|
|
|
21
21
|
|
|
22
22
|
preorder = partialmethod(_traverse, order="preorder")
|
|
23
23
|
postorder = partialmethod(_traverse, order="postorder")
|
|
24
|
+
levelorder = partialmethod(_traverse, order="level")
|
|
24
25
|
|
|
25
|
-
def
|
|
26
|
+
def _get_leaves(self) -> Sequence[Any]:
|
|
26
27
|
return self.tree.get_terminals()
|
|
27
28
|
|
|
28
29
|
@staticmethod
|
|
@@ -16,7 +16,10 @@ class Cogent3DataProvider(TreeDataProvider):
|
|
|
16
16
|
def postorder(self) -> Sequence[Any]:
|
|
17
17
|
return self.tree.postorder()
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def levelorder(self) -> Sequence[Any]:
|
|
20
|
+
return self.tree.levelorder()
|
|
21
|
+
|
|
22
|
+
def _get_leaves(self) -> Sequence[Any]:
|
|
20
23
|
return self.tree.tips()
|
|
21
24
|
|
|
22
25
|
@staticmethod
|
|
@@ -36,7 +36,16 @@ class DendropyDataProvider(TreeDataProvider):
|
|
|
36
36
|
return self.tree.postorder_node_iter()
|
|
37
37
|
return self.tree.postorder_iter()
|
|
38
38
|
|
|
39
|
-
def
|
|
39
|
+
def levelorder(self) -> Any:
|
|
40
|
+
"""Levelorder traversal of the tree.
|
|
41
|
+
|
|
42
|
+
NOTE: This will work on both entire Trees and Nodes (which means a subtree including self).
|
|
43
|
+
"""
|
|
44
|
+
if hasattr(self.tree, "levelorder_node_iter"):
|
|
45
|
+
return self.tree.levelorder_node_iter()
|
|
46
|
+
return self.tree.levelorder_iter()
|
|
47
|
+
|
|
48
|
+
def _get_leaves(self) -> Sequence[Any]:
|
|
40
49
|
"""Get a list of leaves."""
|
|
41
50
|
return self.tree.leaf_nodes()
|
|
42
51
|
|
|
@@ -18,8 +18,9 @@ class Ete4DataProvider(TreeDataProvider):
|
|
|
18
18
|
|
|
19
19
|
preorder = partialmethod(_traverse, order="preorder")
|
|
20
20
|
postorder = partialmethod(_traverse, order="postorder")
|
|
21
|
+
levelorder = partialmethod(_traverse, order="levelorder")
|
|
21
22
|
|
|
22
|
-
def
|
|
23
|
+
def _get_leaves(self) -> Sequence[Any]:
|
|
23
24
|
return self.tree.leaves()
|
|
24
25
|
|
|
25
26
|
@staticmethod
|
|
@@ -64,7 +64,17 @@ class SimpleTreeDataProvider(TreeDataProvider):
|
|
|
64
64
|
|
|
65
65
|
yield from _recur(self.tree)
|
|
66
66
|
|
|
67
|
-
def
|
|
67
|
+
def levelorder(self) -> Iterable[dict[dict | str, Any]]:
|
|
68
|
+
from collections import deque
|
|
69
|
+
|
|
70
|
+
queue = deque([self.get_root()])
|
|
71
|
+
while queue:
|
|
72
|
+
node = queue.popleft()
|
|
73
|
+
for child in self.get_children(node):
|
|
74
|
+
queue.append(child)
|
|
75
|
+
yield node
|
|
76
|
+
|
|
77
|
+
def _get_leaves(self) -> Sequence[Any]:
|
|
68
78
|
def _recur(node):
|
|
69
79
|
if len(node.children) == 0:
|
|
70
80
|
yield node
|
|
@@ -16,7 +16,10 @@ class SkbioDataProvider(TreeDataProvider):
|
|
|
16
16
|
def postorder(self) -> Sequence[Any]:
|
|
17
17
|
return self.tree.postorder()
|
|
18
18
|
|
|
19
|
-
def
|
|
19
|
+
def levelorder(self) -> Sequence[Any]:
|
|
20
|
+
return self.tree.levelorder()
|
|
21
|
+
|
|
22
|
+
def _get_leaves(self) -> Sequence[Any]:
|
|
20
23
|
return self.tree.tips()
|
|
21
24
|
|
|
22
25
|
@staticmethod
|
|
@@ -12,6 +12,7 @@ from typing import (
|
|
|
12
12
|
Any,
|
|
13
13
|
Iterable,
|
|
14
14
|
)
|
|
15
|
+
|
|
15
16
|
# NOTE: __init__ in Protocols has had a difficult gestation
|
|
16
17
|
# https://github.com/python/cpython/issues/88970
|
|
17
18
|
if sys.version_info < (3, 11):
|
|
@@ -156,8 +157,32 @@ class TreeDataProvider(Protocol):
|
|
|
156
157
|
return root_attr
|
|
157
158
|
return self.tree.get_root()
|
|
158
159
|
|
|
159
|
-
def
|
|
160
|
-
"""Get the
|
|
160
|
+
def get_subtree(self, node: TreeType):
|
|
161
|
+
"""Get the subtree rooted at the given node.
|
|
162
|
+
|
|
163
|
+
Parameters:
|
|
164
|
+
node: The node to get the subtree from.
|
|
165
|
+
Returns:
|
|
166
|
+
The subtree rooted at the given node.
|
|
167
|
+
"""
|
|
168
|
+
return self.__class__(node)
|
|
169
|
+
|
|
170
|
+
def get_leaves(self, node: Optional[TreeType] = None) -> Sequence[Any]:
|
|
171
|
+
"""Get the leaves of the entire tree or a subtree.
|
|
172
|
+
|
|
173
|
+
Parameters:
|
|
174
|
+
node: The node to get the leaves from. If None, get from the entire
|
|
175
|
+
tree.
|
|
176
|
+
Returns:
|
|
177
|
+
The leaves or tips of the tree or node-anchored subtree.
|
|
178
|
+
"""
|
|
179
|
+
if node is None:
|
|
180
|
+
return self._get_leaves()
|
|
181
|
+
else:
|
|
182
|
+
return self.get_subtree(node)._get_leaves()
|
|
183
|
+
|
|
184
|
+
def _get_leaves(self) -> Sequence[Any]:
|
|
185
|
+
"""Get the whole tree leaves/tips in a provider-specific data structure.
|
|
161
186
|
|
|
162
187
|
Returns:
|
|
163
188
|
The leaves or tips of the tree.
|
|
@@ -235,8 +260,6 @@ class TreeDataProvider(Protocol):
|
|
|
235
260
|
NOTE: individual providers may implement more efficient versions of
|
|
236
261
|
this function if desired.
|
|
237
262
|
"""
|
|
238
|
-
provider = self.__class__
|
|
239
|
-
|
|
240
263
|
# Find leaves of the selected nodes
|
|
241
264
|
leaves = set()
|
|
242
265
|
for node in nodes:
|
|
@@ -244,7 +267,7 @@ class TreeDataProvider(Protocol):
|
|
|
244
267
|
if len(self.get_children(node)) == 0:
|
|
245
268
|
leaves.add(node)
|
|
246
269
|
else:
|
|
247
|
-
leaves |= set(
|
|
270
|
+
leaves |= set(self.get_leaves(node))
|
|
248
271
|
|
|
249
272
|
# Look for nodes with the same set of leaves, starting from the bottom
|
|
250
273
|
# and stopping at the first (i.e. lowest) hit.
|
|
@@ -253,7 +276,7 @@ class TreeDataProvider(Protocol):
|
|
|
253
276
|
if len(self.get_children(node)) == 0:
|
|
254
277
|
leaves_node = {node}
|
|
255
278
|
else:
|
|
256
|
-
leaves_node = set(
|
|
279
|
+
leaves_node = set(self.get_leaves(node))
|
|
257
280
|
if leaves <= leaves_node:
|
|
258
281
|
root = node
|
|
259
282
|
break
|
|
@@ -285,9 +308,26 @@ class TreeDataProvider(Protocol):
|
|
|
285
308
|
orientation = "right"
|
|
286
309
|
elif layout == "vertical":
|
|
287
310
|
orientation = "descending"
|
|
288
|
-
elif layout
|
|
311
|
+
elif layout in ("radial", "equalangle", "daylight"):
|
|
289
312
|
orientation = "clockwise"
|
|
290
313
|
|
|
314
|
+
# Validate orientation
|
|
315
|
+
valid = (layout == "horizontal") and (orientation in ("right", "left"))
|
|
316
|
+
valid |= (layout == "vertical") and (orientation in ("ascending", "descending"))
|
|
317
|
+
valid |= (layout == "radial") and (
|
|
318
|
+
orientation in ("clockwise", "counterclockwise", "left", "right")
|
|
319
|
+
)
|
|
320
|
+
valid |= (layout == "equalangle") and (
|
|
321
|
+
orientation in ("clockwise", "counterclockwise", "left", "right")
|
|
322
|
+
)
|
|
323
|
+
valid |= (layout == "daylight") and (
|
|
324
|
+
orientation in ("clockwise", "counterclockwise", "left", "right")
|
|
325
|
+
)
|
|
326
|
+
if not valid:
|
|
327
|
+
raise ValueError(
|
|
328
|
+
f"Orientation '{orientation}' is not valid for layout '{layout}'.",
|
|
329
|
+
)
|
|
330
|
+
|
|
291
331
|
tree_data = {
|
|
292
332
|
"root": self.get_root(),
|
|
293
333
|
"rooted": self.is_rooted(),
|
|
@@ -304,8 +344,10 @@ class TreeDataProvider(Protocol):
|
|
|
304
344
|
root=tree_data["root"],
|
|
305
345
|
preorder_fun=self.preorder,
|
|
306
346
|
postorder_fun=self.postorder,
|
|
347
|
+
levelorder_fun=self.levelorder,
|
|
307
348
|
children_fun=self.get_children,
|
|
308
349
|
branch_length_fun=self.get_branch_length_default_to_one,
|
|
350
|
+
leaves_fun=self.get_leaves,
|
|
309
351
|
**layout_style,
|
|
310
352
|
)
|
|
311
353
|
if layout in ("radial",):
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tree layout algorithms.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import (
|
|
6
|
+
Any,
|
|
7
|
+
)
|
|
8
|
+
from collections.abc import (
|
|
9
|
+
Hashable,
|
|
10
|
+
Callable,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from .rooted import (
|
|
14
|
+
_horizontal_tree_layout,
|
|
15
|
+
_vertical_tree_layout,
|
|
16
|
+
_radial_tree_layout,
|
|
17
|
+
)
|
|
18
|
+
from .unrooted import (
|
|
19
|
+
_equalangle_tree_layout,
|
|
20
|
+
_daylight_tree_layout,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def compute_tree_layout(
|
|
25
|
+
layout: str,
|
|
26
|
+
orientation: str,
|
|
27
|
+
root: Any,
|
|
28
|
+
preorder_fun: Callable,
|
|
29
|
+
postorder_fun: Callable,
|
|
30
|
+
levelorder_fun: Callable,
|
|
31
|
+
children_fun: Callable,
|
|
32
|
+
branch_length_fun: Callable,
|
|
33
|
+
leaves_fun: Callable,
|
|
34
|
+
**kwargs,
|
|
35
|
+
) -> dict[Hashable, list[float]]:
|
|
36
|
+
"""Compute the layout for a tree.
|
|
37
|
+
|
|
38
|
+
Parameters:
|
|
39
|
+
layout: The name of the layout, e.g. "horizontal", "vertical", or "radial".
|
|
40
|
+
orientation: The orientation of the layout, e.g. "right", "left", "descending",
|
|
41
|
+
"ascending", "clockwise", "anticlockwise".
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
A layout dictionary with node positions.
|
|
45
|
+
"""
|
|
46
|
+
kwargs["root"] = root
|
|
47
|
+
kwargs["preorder_fun"] = preorder_fun
|
|
48
|
+
kwargs["postorder_fun"] = postorder_fun
|
|
49
|
+
kwargs["levelorder_fun"] = levelorder_fun
|
|
50
|
+
kwargs["children_fun"] = children_fun
|
|
51
|
+
kwargs["orientation"] = orientation
|
|
52
|
+
kwargs["branch_length_fun"] = branch_length_fun
|
|
53
|
+
kwargs["leaves_fun"] = leaves_fun
|
|
54
|
+
|
|
55
|
+
# Angular or not, the vertex layout is unchanged. Since we do not
|
|
56
|
+
# currently compute an edge layout here, we can ignore the option.
|
|
57
|
+
kwargs.pop("angular", None)
|
|
58
|
+
|
|
59
|
+
if layout == "radial":
|
|
60
|
+
layout_dict = _radial_tree_layout(**kwargs)
|
|
61
|
+
elif layout == "horizontal":
|
|
62
|
+
layout_dict = _horizontal_tree_layout(**kwargs)
|
|
63
|
+
elif layout == "vertical":
|
|
64
|
+
layout_dict = _vertical_tree_layout(**kwargs)
|
|
65
|
+
elif layout == "equalangle":
|
|
66
|
+
layout_dict = _equalangle_tree_layout(**kwargs)
|
|
67
|
+
elif layout == "daylight":
|
|
68
|
+
layout_dict = _daylight_tree_layout(**kwargs)
|
|
69
|
+
else:
|
|
70
|
+
raise ValueError(f"Tree layout not available: {layout}")
|
|
71
|
+
|
|
72
|
+
return layout_dict
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Rooted tree layout for iplotx library.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from typing import (
|
|
@@ -14,55 +14,13 @@ from collections.abc import (
|
|
|
14
14
|
import numpy as np
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
def compute_tree_layout(
|
|
18
|
-
layout: str,
|
|
19
|
-
orientation: str,
|
|
20
|
-
root: Any,
|
|
21
|
-
preorder_fun: Callable,
|
|
22
|
-
postorder_fun: Callable,
|
|
23
|
-
children_fun: Callable,
|
|
24
|
-
branch_length_fun: Callable,
|
|
25
|
-
**kwargs,
|
|
26
|
-
) -> dict[Hashable, list[float]]:
|
|
27
|
-
"""Compute the layout for a tree.
|
|
28
|
-
|
|
29
|
-
Parameters:
|
|
30
|
-
layout: The name of the layout, e.g. "horizontal", "vertical", or "radial".
|
|
31
|
-
orientation: The orientation of the layout, e.g. "right", "left", "descending",
|
|
32
|
-
"ascending", "clockwise", "anticlockwise".
|
|
33
|
-
|
|
34
|
-
Returns:
|
|
35
|
-
A layout dictionary with node positions.
|
|
36
|
-
"""
|
|
37
|
-
kwargs["root"] = root
|
|
38
|
-
kwargs["preorder_fun"] = preorder_fun
|
|
39
|
-
kwargs["postorder_fun"] = postorder_fun
|
|
40
|
-
kwargs["children_fun"] = children_fun
|
|
41
|
-
kwargs["branch_length_fun"] = branch_length_fun
|
|
42
|
-
kwargs["orientation"] = orientation
|
|
43
|
-
|
|
44
|
-
# Angular or not, the vertex layout is unchanged. Since we do not
|
|
45
|
-
# currently compute an edge layout here, we can ignore the option.
|
|
46
|
-
kwargs.pop("angular", None)
|
|
47
|
-
|
|
48
|
-
if layout == "radial":
|
|
49
|
-
layout_dict = _radial_tree_layout(**kwargs)
|
|
50
|
-
elif layout == "horizontal":
|
|
51
|
-
layout_dict = _horizontal_tree_layout(**kwargs)
|
|
52
|
-
elif layout == "vertical":
|
|
53
|
-
layout_dict = _vertical_tree_layout(**kwargs)
|
|
54
|
-
else:
|
|
55
|
-
raise ValueError(f"Tree layout not available: {layout}")
|
|
56
|
-
|
|
57
|
-
return layout_dict
|
|
58
|
-
|
|
59
|
-
|
|
60
17
|
def _horizontal_tree_layout_right(
|
|
61
18
|
root: Any,
|
|
62
19
|
preorder_fun: Callable,
|
|
63
20
|
postorder_fun: Callable,
|
|
64
21
|
children_fun: Callable,
|
|
65
22
|
branch_length_fun: Callable,
|
|
23
|
+
**kwargs,
|
|
66
24
|
) -> dict[Hashable, list[float]]:
|
|
67
25
|
"""Build a tree layout horizontally, left to right.
|
|
68
26
|
|
|
@@ -173,7 +131,7 @@ def _radial_tree_layout(
|
|
|
173
131
|
360, it leaves a small gap at the end to ensure the first and last leaf
|
|
174
132
|
are not overlapping.
|
|
175
133
|
Returns:
|
|
176
|
-
A dictionary with the
|
|
134
|
+
A dictionary with the layout.
|
|
177
135
|
"""
|
|
178
136
|
# Short form
|
|
179
137
|
th = start * np.pi / 180
|