iplotx 1.2.0__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.0 → iplotx-1.3.0}/.github/workflows/test.yml +1 -1
- {iplotx-1.2.0 → iplotx-1.3.0}/.gitignore +4 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/PKG-INFO +13 -6
- {iplotx-1.2.0 → iplotx-1.3.0}/README.md +10 -3
- iplotx-1.3.0/docs/source/code_of_conduct.rst +145 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/index.md +1 -0
- {iplotx-1.2.0 → 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.0 → iplotx-1.3.0}/iplotx/edge/arrow.py +6 -1
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/__init__.py +19 -8
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/providers/tree/biopython.py +2 -1
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/providers/tree/cogent3.py +4 -1
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/providers/tree/dendropy.py +10 -1
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/providers/tree/ete4.py +2 -1
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/providers/tree/simple.py +13 -4
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/providers/tree/skbio.py +4 -1
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/typing.py +62 -10
- iplotx-1.3.0/iplotx/layout/__init__.py +9 -0
- iplotx-1.3.0/iplotx/layout/tree/__init__.py +72 -0
- iplotx-1.2.0/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.0 → iplotx-1.3.0}/iplotx/network/__init__.py +3 -4
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/tree/__init__.py +5 -2
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/version.py +1 -1
- {iplotx-1.2.0 → iplotx-1.3.0}/pyproject.toml +2 -2
- 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.0 → iplotx-1.3.0}/tests/test_ete4.py +22 -4
- {iplotx-1.2.0 → iplotx-1.3.0}/uv.lock +509 -48
- iplotx-1.2.0/tests/baseline_images/test_biopython/leafedges.png +0 -0
- iplotx-1.2.0/tests/baseline_images/test_biopython/tree_radial.png +0 -0
- iplotx-1.2.0/tests/baseline_images/test_cogent3/tree_radial.png +0 -0
- iplotx-1.2.0/tests/baseline_images/test_ete4/tree_radial.png +0 -0
- iplotx-1.2.0/tests/baseline_images/test_skbio/tree_radial.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/.github/workflows/publish.yml +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/.pre-commit-config.yaml +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/.readthedocs.yaml +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/LICENSE +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/MANIFEST.in +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/assets/pylint.svg +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/Makefile +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/make.bat +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/_static/banner.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/_static/custom-icons.js +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/_static/custom.css +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/_static/graph_basic.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/_templates/layout.html +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/api/artists.md +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/api/complete_style_specification.md +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/api/plotting.md +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/api/providers.md +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/api/style.md +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/api.md +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/conf.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/images/sphx_glr_plot_basic_001.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/images/thumb/sphx_glr_plot_basic_thumb.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/installing.md +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/providers.md +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/docs/source/style.md +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/basic/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/basic/plot_3d.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/basic/plot_basic.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/basic/plot_big_curves.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/basic/plot_dag.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/basic/plot_directed.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/basic/plot_grouping.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/basic/plot_house.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/basic/plot_loops.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/basic/plot_simple_path.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/data/80201010000000001.mst +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/data/GN-tree.json +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/data/breast_cancer_string_interactions_short.tsv +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/data/breast_cancer_string_network_coordinates.tsv +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/data/cell_cycle_arrest_string_interactions_short.tsv +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/data/cell_cycle_arrest_string_network_coordinates.tsv +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/data/fevo-08-588430_DataSheet1_S1.csv +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/plot_animal_phylogeny.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/plot_antibody_clone.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/plot_breast_cancer_ppi.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/plot_cell_cycle_arrest.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/plot_food_network.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/plot_foraging_table.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/plot_pollinators.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/plot_ppi.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/biology/plot_tca_cycle.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/data/chess_masters_WCC.pgn.bz2 +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/data/knuth_miles.txt.gz +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_arrowlawn.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_chess_masters.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_cliques.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_cluster_layout.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_company_structure.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_complex.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_financial_network.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_knuth_miles.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_labels_and_colors.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_max_bipartite_matching.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_minimum_spanning_trees.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_multipartite_layout.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_parallel_igraph_networkx.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_redblack.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_shortest_path.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_simple_networkx.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_social_network_circles.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_traveling_salesman.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/network_science/plot_with_colorbar.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/other/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/other/plot_animation.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/other/plot_edit_artists.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/other/plot_feedbacks.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/other/plot_graph.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/other/plot_mouse_hover.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/other/plot_train.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_arrows.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_depthshade.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_edgepadding.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_elements.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_four_grids.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_halfarrows.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_multistyle.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_ports.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_style.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_tension.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_vertexmarkers.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_voronoi.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/style/plot_waypoints.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/data/tree-with-support.json +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_angular_waypoints.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_biopython_tree.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_cladeedges.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_cogent3_layouts.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_cogent3_tree.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_dendropy.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_double_tree.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_elements_tree.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_ete4.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_leafedges.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_leafedges_and_cascades.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_scalebar.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_skbio_tree.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_split_edges.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_style_tree.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_support.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_tree_node_background.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_tree_style_clades.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/tree/plot_trees_of_trees.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/zero_dependency/GALLERY_HEADER.rst +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/zero_dependency/plot_simplenetworkdataprovider.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/gallery/zero_dependency/plot_simpletreedataprovider.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/__init__.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/art3d/edge/__init__.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/art3d/edge/arrow.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/art3d/edge/geometry.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/art3d/vertex.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/artists.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/edge/__init__.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/edge/geometry.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/edge/leaf.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/edge/ports.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/heuristics.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/providers/network/graph_tool.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/providers/network/igraph.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/providers/network/networkx.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/ingest/providers/network/simple.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/label.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/network/groups.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/plotting.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/style/__init__.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/style/leaf_info.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/style/library.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/tree/cascades.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/tree/scalebar.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/typing.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/utils/geometry.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/utils/internal.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/utils/matplotlib.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/utils/style.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/iplotx/vertex.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/scripts/copy_github_release_into_version.sh +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/scripts/make_banner.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/scripts/update_pylint_badge.sh +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_biopython/cascades.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_biopython/directed_child.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_biopython/leaf_labels.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_biopython/leaf_labels_hmargin.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_biopython/show_support.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_biopython/tree_basic.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_cogent3/leaf_labels.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_cogent3/leaf_labels_hmargin.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_cogent3/tree_basic.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/cascades.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/directed_child.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/leaf_labels.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/leaf_labels_hmargin.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/leafedges.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/tree_basic.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_dendropy/tree_radial.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_doubletree/tree_gap.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_doubletree/tree_nogap.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_ete4/leaf_labels.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_ete4/leaf_labels_hmargin.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_ete4/split_edges.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_ete4/tree_basic.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_graph_tool/graph_basic.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_graph_tool/graph_directed.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/clustering_directed.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/clustering_directed_large.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_basic.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_directed.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_directed_curved_loops.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_edit_children.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_labels.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_layout_attribute.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_null.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_squares_directed.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_vertexsize.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/graph_with_curved_edges.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/igraph_layout_object.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph/multigraph_with_curved_edges_undirected.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph_3d/directed.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph_3d/undirected.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_igraph_3d/vertex_labels.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/cluster-layout.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/complex.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/complex_rotatelabels.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/directed_graph.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/directed_graph_with_colorbar.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/empty_graph.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/flat_style.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/house_with_colors.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/labels_and_colors.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/shortest_path.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_networkx/simple_graph.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_simple_network_provider/graph_basic.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_simple_network_provider/graph_directed.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_simple_network_provider/graph_labels.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_skbio/leaf_labels.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_skbio/leaf_labels_hmargin.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/baseline_images/test_skbio/tree_basic.png +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_arrows.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_biopython.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_cascades.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_cogent3.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_dendropy.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_doubletree.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_edge.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_edge_geometry.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_geometry.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_graph_tool.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_heuristics.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_igraph.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_igraph_3d.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_ingest_protocols.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_matplotlib_utils.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_network_hotload.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_networkx.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_ports.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_simple_network_provider.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_simple_tree_provider.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_skbio.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_style.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/test_vertex.py +0 -0
- {iplotx-1.2.0 → iplotx-1.3.0}/tests/utils.py +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
|
|
@@ -26,8 +26,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
26
26
|
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
27
27
|
Classifier: Topic :: System :: Networking
|
|
28
28
|
Classifier: Typing :: Typed
|
|
29
|
-
Requires-Python: >=3.
|
|
30
|
-
Requires-Dist: matplotlib>=
|
|
29
|
+
Requires-Python: >=3.10
|
|
30
|
+
Requires-Dist: matplotlib>=3.10.0
|
|
31
31
|
Requires-Dist: numpy>=2.0.0
|
|
32
32
|
Requires-Dist: pandas>=2.0.0
|
|
33
33
|
Provides-Extra: igraph
|
|
@@ -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. ✅
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
.. _scipy-coc:
|
|
2
|
+
|
|
3
|
+
iplotx Code of Conduct
|
|
4
|
+
======================
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Introduction
|
|
8
|
+
------------
|
|
9
|
+
|
|
10
|
+
This code of conduct applies to all spaces managed by the iplotx project,
|
|
11
|
+
including all public and private mailing lists, issue trackers, wikis, blogs,
|
|
12
|
+
and any other communication channel used by our community. The iplotx
|
|
13
|
+
project does not organize in-person events, however, events related to our
|
|
14
|
+
community should have a code of conduct similar in spirit to this one.
|
|
15
|
+
|
|
16
|
+
This code of conduct should be honored by everyone who participates in
|
|
17
|
+
the iplotx community formally or informally, or claims any affiliation with the
|
|
18
|
+
project, in any project-related activities, and, especially, when representing the
|
|
19
|
+
project, in any role.
|
|
20
|
+
|
|
21
|
+
This code is neither exhaustive nor complete. It serves to distill our common
|
|
22
|
+
understanding of a collaborative, shared environment and goals. Please try to
|
|
23
|
+
follow this code in spirit as much as in letter, to create a friendly and
|
|
24
|
+
productive environment that enriches the surrounding community.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Specific guidelines
|
|
28
|
+
-------------------
|
|
29
|
+
|
|
30
|
+
We strive to:
|
|
31
|
+
|
|
32
|
+
1. Be open. We invite anyone to participate in our community. We prefer to use
|
|
33
|
+
public methods of communication for project-related messages, unless
|
|
34
|
+
discussing something sensitive. This applies to messages for help or
|
|
35
|
+
project-related support, too; not only is a public-support request much more
|
|
36
|
+
likely to result in an answer to a question, it also ensures that any
|
|
37
|
+
inadvertent mistakes in answering are more easily detected and corrected.
|
|
38
|
+
|
|
39
|
+
2. Be empathetic, welcoming, friendly, and patient. We work together to resolve
|
|
40
|
+
conflict, and assume good intentions. We may all experience some frustration
|
|
41
|
+
from time to time, but we do not allow frustration to turn into a personal
|
|
42
|
+
attack. A community where people feel uncomfortable or threatened is not a
|
|
43
|
+
productive one.
|
|
44
|
+
|
|
45
|
+
3. Be collaborative. Our work will be used by other people, and in turn we will
|
|
46
|
+
depend on the work of others. When we make something for the benefit of the
|
|
47
|
+
project, we are willing to explain to others how it works, so that they can
|
|
48
|
+
build on the work to make it even better. Any decision we make will affect
|
|
49
|
+
users and colleagues, and we take those consequences seriously when making
|
|
50
|
+
decisions.
|
|
51
|
+
|
|
52
|
+
4. Be inquisitive. Nobody knows everything! Asking questions early avoids many
|
|
53
|
+
problems later, so we encourage questions, although we may direct them to
|
|
54
|
+
the appropriate forum. We will try hard to be responsive and helpful.
|
|
55
|
+
|
|
56
|
+
5. Be careful in the words that we choose. We are careful and respectful in
|
|
57
|
+
our communication and we take responsibility for our own speech. Be kind to
|
|
58
|
+
others. Do not insult or put down other participants. We will not accept
|
|
59
|
+
harassment or other exclusionary behavior, such as:
|
|
60
|
+
|
|
61
|
+
- Violent threats or language directed against another person.
|
|
62
|
+
- Sexist, racist, or otherwise discriminatory jokes and language.
|
|
63
|
+
- Posting sexually explicit or violent material.
|
|
64
|
+
- Posting (or threatening to post) other people's personally identifying information ("doxing").
|
|
65
|
+
- Sharing private content, such as emails sent privately or non-publicly,
|
|
66
|
+
or unlogged forums, such as IRC channel history, without the sender's consent.
|
|
67
|
+
- Personal insults, especially those using racist or sexist terms.
|
|
68
|
+
- Unwelcome sexual attention.
|
|
69
|
+
- Excessive profanity. Please avoid swearwords; people differ greatly in their sensitivity to swearing.
|
|
70
|
+
- Repeated harassment of others. In general, if someone asks you to stop, then stop.
|
|
71
|
+
- Advocating for, or encouraging, any of the above behavior.
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
Diversity statement
|
|
75
|
+
-------------------
|
|
76
|
+
|
|
77
|
+
The iplotx project welcomes and encourages participation by everyone. We are
|
|
78
|
+
committed to being a community that everyone enjoys being part of. Although
|
|
79
|
+
we may not always be able to accommodate each individual's preferences, we try
|
|
80
|
+
our best to treat everyone kindly.
|
|
81
|
+
|
|
82
|
+
No matter how you identify yourself or how others perceive you: we welcome you.
|
|
83
|
+
Though no list can hope to be comprehensive, we explicitly honor diversity in:
|
|
84
|
+
age, culture, ethnicity, genotype, gender identity or expression, language,
|
|
85
|
+
national origin, neurotype, phenotype, political beliefs, profession, race,
|
|
86
|
+
religion, sexual orientation, socioeconomic status, subculture and technical
|
|
87
|
+
ability, to the extent that these do not conflict with this code of conduct.
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
Though we welcome people fluent in all languages, iplotx development is
|
|
91
|
+
conducted in English.
|
|
92
|
+
|
|
93
|
+
Standards for behavior in the iplotx community are detailed in the Code of
|
|
94
|
+
Conduct above. Participants in our community should uphold these standards
|
|
95
|
+
in all their interactions and help others to do so as well (see next section).
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
Reporting guidelines
|
|
99
|
+
--------------------
|
|
100
|
+
|
|
101
|
+
We know that it is painfully common for internet communication to start at or
|
|
102
|
+
devolve into obvious and flagrant abuse. We also recognize that sometimes
|
|
103
|
+
people may have a bad day, or be unaware of some of the guidelines in this Code
|
|
104
|
+
of Conduct. Please keep this in mind when deciding on how to respond to a
|
|
105
|
+
breach of this Code.
|
|
106
|
+
|
|
107
|
+
For clearly intentional breaches, report those to the Code of Conduct committee
|
|
108
|
+
(see below). For possibly unintentional breaches, you may reply to the person
|
|
109
|
+
and point out this Code of Conduct (either in public or in private, whatever is
|
|
110
|
+
most appropriate). If you would prefer not to do that, please feel free to
|
|
111
|
+
report to the Code of Conduct committee directly, or ask the committee for
|
|
112
|
+
advice, in confidence.
|
|
113
|
+
|
|
114
|
+
You can report issues to the iplotx core developer Fabio Zanini, at
|
|
115
|
+
fabio.zanini@unsw.edu.au.
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
Incident reporting resolution & Code of Conduct enforcement
|
|
119
|
+
-----------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
We will investigate and respond to all complaints. This Code of Conduct
|
|
122
|
+
Committee will protect the identity of the reporter, and treat the content
|
|
123
|
+
of complaints as confidential (unless the reporter requests otherwise).
|
|
124
|
+
|
|
125
|
+
In case of severe and obvious breaches, e.g., personal threat or violent, sexist
|
|
126
|
+
or racist language, we will immediately do our utmost to disconnect the
|
|
127
|
+
originator from iplotx communication channels; please see the manual for details.
|
|
128
|
+
|
|
129
|
+
In cases not involving clear severe and obvious breaches of this code of
|
|
130
|
+
conduct, the process for acting on any received code of conduct violation
|
|
131
|
+
report will be:
|
|
132
|
+
|
|
133
|
+
1. Acknowledgement that the report has been received
|
|
134
|
+
2. Reasonable discussion/feedback
|
|
135
|
+
3. Mediation (if feedback didn't help, and only if both reporter and reportee agree to this)
|
|
136
|
+
4. Enforcement via transparent decision by the Code of Conduct Committee
|
|
137
|
+
|
|
138
|
+
The committee will respond to any report as soon as possible, and at most
|
|
139
|
+
within 72 hours.
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
Endnotes
|
|
143
|
+
--------
|
|
144
|
+
|
|
145
|
+
This document was adapted from the `SciPy Code of Conduct <https://scipy.github.io/devdocs/dev/conduct/code_of_conduct.html>`_.
|
|
@@ -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
|
+
)
|
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
Module for edge arrows in iplotx.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import sys
|
|
6
|
+
if sys.version_info < (3, 11):
|
|
7
|
+
from typing_extensions import Never
|
|
8
|
+
else:
|
|
9
|
+
from typing import Never
|
|
10
|
+
from typing import Optional
|
|
6
11
|
|
|
7
12
|
from math import atan2, cos, sin
|
|
8
13
|
import numpy as np
|
|
@@ -2,16 +2,24 @@
|
|
|
2
2
|
This module focuses on how to ingest network/tree data into standard data structures no matter what library they come from.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import pkgutil
|
|
7
|
-
import importlib
|
|
8
|
-
import warnings
|
|
5
|
+
import sys
|
|
9
6
|
from typing import (
|
|
10
7
|
Optional,
|
|
11
8
|
Sequence,
|
|
12
|
-
Protocol,
|
|
13
9
|
)
|
|
10
|
+
|
|
11
|
+
# NOTE: __init__ in Protocols has had a difficult gestation
|
|
12
|
+
# https://github.com/python/cpython/issues/88970
|
|
13
|
+
if sys.version_info < (3, 11):
|
|
14
|
+
Protocol = object
|
|
15
|
+
else:
|
|
16
|
+
from typing import Protocol
|
|
17
|
+
|
|
14
18
|
from collections.abc import Hashable
|
|
19
|
+
import pathlib
|
|
20
|
+
import pkgutil
|
|
21
|
+
import importlib
|
|
22
|
+
import warnings
|
|
15
23
|
import pandas as pd
|
|
16
24
|
|
|
17
25
|
from ..typing import (
|
|
@@ -35,6 +43,9 @@ provider_protocols = {
|
|
|
35
43
|
data_providers: dict[str, dict[str, Protocol]] = {kind: {} for kind in provider_protocols}
|
|
36
44
|
for kind in data_providers:
|
|
37
45
|
providers_path = pathlib.Path(__file__).parent.joinpath("providers").joinpath(kind)
|
|
46
|
+
if sys.version_info < (3, 11):
|
|
47
|
+
providers_path = str(providers_path)
|
|
48
|
+
|
|
38
49
|
for importer, module_name, _ in pkgutil.iter_modules([providers_path]):
|
|
39
50
|
module = importlib.import_module(f"iplotx.ingest.providers.{kind}.{module_name}")
|
|
40
51
|
for key, val in module.__dict__.items():
|
|
@@ -138,11 +149,11 @@ def ingest_tree_data(
|
|
|
138
149
|
|
|
139
150
|
|
|
140
151
|
# INTERNAL FUNCTIONS
|
|
141
|
-
def _update_data_providers(kind):
|
|
142
|
-
"""Update data
|
|
152
|
+
def _update_data_providers(kind: str):
|
|
153
|
+
"""Update data providers dynamically from external packages."""
|
|
143
154
|
discovered_providers = importlib.metadata.entry_points(group=f"iplotx.{kind}_data_providers")
|
|
144
155
|
for entry_point in discovered_providers:
|
|
145
|
-
if entry_point.name not in data_providers[
|
|
156
|
+
if entry_point.name not in data_providers[kind]:
|
|
146
157
|
try:
|
|
147
158
|
data_providers[kind][entry_point.name] = entry_point.load()
|
|
148
159
|
except Exception as e:
|
|
@@ -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
|
|
@@ -3,7 +3,6 @@ from typing import (
|
|
|
3
3
|
Optional,
|
|
4
4
|
Sequence,
|
|
5
5
|
Iterable,
|
|
6
|
-
Self,
|
|
7
6
|
)
|
|
8
7
|
|
|
9
8
|
from ...typing import (
|
|
@@ -19,12 +18,12 @@ class SimpleTree:
|
|
|
19
18
|
branch_length: Length of the branch leading to this node/tree.
|
|
20
19
|
"""
|
|
21
20
|
|
|
22
|
-
children: Sequence
|
|
21
|
+
children: Sequence = []
|
|
23
22
|
branch_length: float = 1
|
|
24
23
|
name: str = ""
|
|
25
24
|
|
|
26
25
|
@classmethod
|
|
27
|
-
def from_dict(cls, data: dict)
|
|
26
|
+
def from_dict(cls, data: dict):
|
|
28
27
|
"""Create a SimpleTree from a dictionary.
|
|
29
28
|
|
|
30
29
|
Parameters:
|
|
@@ -65,7 +64,17 @@ class SimpleTreeDataProvider(TreeDataProvider):
|
|
|
65
64
|
|
|
66
65
|
yield from _recur(self.tree)
|
|
67
66
|
|
|
68
|
-
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]:
|
|
69
78
|
def _recur(node):
|
|
70
79
|
if len(node.children) == 0:
|
|
71
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
|
|
@@ -5,15 +5,21 @@ Networkx and trees are treated separately for practical reasons: many tree analy
|
|
|
5
5
|
work as well on general networks.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
import sys
|
|
8
9
|
from typing import (
|
|
9
|
-
NotRequired,
|
|
10
|
-
TypedDict,
|
|
11
|
-
Protocol,
|
|
12
10
|
Optional,
|
|
13
11
|
Sequence,
|
|
14
12
|
Any,
|
|
15
13
|
Iterable,
|
|
16
14
|
)
|
|
15
|
+
|
|
16
|
+
# NOTE: __init__ in Protocols has had a difficult gestation
|
|
17
|
+
# https://github.com/python/cpython/issues/88970
|
|
18
|
+
if sys.version_info < (3, 11):
|
|
19
|
+
Protocol = object
|
|
20
|
+
else:
|
|
21
|
+
from typing import Protocol
|
|
22
|
+
|
|
17
23
|
from collections.abc import Hashable
|
|
18
24
|
import numpy as np
|
|
19
25
|
import pandas as pd
|
|
@@ -26,6 +32,11 @@ from .heuristics import (
|
|
|
26
32
|
normalise_tree_layout,
|
|
27
33
|
)
|
|
28
34
|
|
|
35
|
+
if sys.version_info < (3, 11):
|
|
36
|
+
from typing_extensions import TypedDict, NotRequired
|
|
37
|
+
else:
|
|
38
|
+
from typing import TypedDict, NotRequired
|
|
39
|
+
|
|
29
40
|
|
|
30
41
|
class NetworkData(TypedDict):
|
|
31
42
|
"""Network data structure for iplotx."""
|
|
@@ -146,8 +157,32 @@ class TreeDataProvider(Protocol):
|
|
|
146
157
|
return root_attr
|
|
147
158
|
return self.tree.get_root()
|
|
148
159
|
|
|
149
|
-
def
|
|
150
|
-
"""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.
|
|
151
186
|
|
|
152
187
|
Returns:
|
|
153
188
|
The leaves or tips of the tree.
|
|
@@ -225,8 +260,6 @@ class TreeDataProvider(Protocol):
|
|
|
225
260
|
NOTE: individual providers may implement more efficient versions of
|
|
226
261
|
this function if desired.
|
|
227
262
|
"""
|
|
228
|
-
provider = self.__class__
|
|
229
|
-
|
|
230
263
|
# Find leaves of the selected nodes
|
|
231
264
|
leaves = set()
|
|
232
265
|
for node in nodes:
|
|
@@ -234,7 +267,7 @@ class TreeDataProvider(Protocol):
|
|
|
234
267
|
if len(self.get_children(node)) == 0:
|
|
235
268
|
leaves.add(node)
|
|
236
269
|
else:
|
|
237
|
-
leaves |= set(
|
|
270
|
+
leaves |= set(self.get_leaves(node))
|
|
238
271
|
|
|
239
272
|
# Look for nodes with the same set of leaves, starting from the bottom
|
|
240
273
|
# and stopping at the first (i.e. lowest) hit.
|
|
@@ -243,7 +276,7 @@ class TreeDataProvider(Protocol):
|
|
|
243
276
|
if len(self.get_children(node)) == 0:
|
|
244
277
|
leaves_node = {node}
|
|
245
278
|
else:
|
|
246
|
-
leaves_node = set(
|
|
279
|
+
leaves_node = set(self.get_leaves(node))
|
|
247
280
|
if leaves <= leaves_node:
|
|
248
281
|
root = node
|
|
249
282
|
break
|
|
@@ -275,9 +308,26 @@ class TreeDataProvider(Protocol):
|
|
|
275
308
|
orientation = "right"
|
|
276
309
|
elif layout == "vertical":
|
|
277
310
|
orientation = "descending"
|
|
278
|
-
elif layout
|
|
311
|
+
elif layout in ("radial", "equalangle", "daylight"):
|
|
279
312
|
orientation = "clockwise"
|
|
280
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
|
+
|
|
281
331
|
tree_data = {
|
|
282
332
|
"root": self.get_root(),
|
|
283
333
|
"rooted": self.is_rooted(),
|
|
@@ -294,8 +344,10 @@ class TreeDataProvider(Protocol):
|
|
|
294
344
|
root=tree_data["root"],
|
|
295
345
|
preorder_fun=self.preorder,
|
|
296
346
|
postorder_fun=self.postorder,
|
|
347
|
+
levelorder_fun=self.levelorder,
|
|
297
348
|
children_fun=self.get_children,
|
|
298
349
|
branch_length_fun=self.get_branch_length_default_to_one,
|
|
350
|
+
leaves_fun=self.get_leaves,
|
|
299
351
|
**layout_style,
|
|
300
352
|
)
|
|
301
353
|
if layout in ("radial",):
|