iplotx 1.0.0__tar.gz → 1.1.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.1.0/.github/workflows/test.yml +86 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/PKG-INFO +7 -6
- {iplotx-1.0.0 → iplotx-1.1.0}/README.md +6 -5
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/index.md +1 -1
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/sg_execution_times.rst +6 -3
- iplotx-1.1.0/gallery/tree/plot_double_tree.py +56 -0
- iplotx-1.1.0/iplotx/ingest/providers/network/graph_tool.py +100 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/layout.py +30 -1
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/tree/__init__.py +3 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/tree/scalebar.py +4 -3
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/version.py +1 -1
- iplotx-1.1.0/tests/baseline_images/test_graph_tool/graph_basic.png +1 -0
- iplotx-1.1.0/tests/baseline_images/test_graph_tool/graph_directed.png +1 -0
- iplotx-1.1.0/tests/test_graph_tool.py +44 -0
- iplotx-1.0.0/.github/workflows/test.yml +0 -43
- {iplotx-1.0.0 → iplotx-1.1.0}/.github/workflows/publish.yml +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/.gitignore +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/.pre-commit-config.yaml +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/.readthedocs.yaml +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/LICENSE +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/MANIFEST.in +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/assets/pylint.svg +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/Makefile +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/make.bat +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/_static/banner.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/_static/custom-icons.js +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/_static/custom.css +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/_static/graph_basic.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/_templates/layout.html +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/api/artists.md +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/api/complete_style_specification.md +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/api/plotting.md +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/api/providers.md +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/api/style.md +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/api.md +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/conf.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/images/sphx_glr_plot_basic_001.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/images/thumb/sphx_glr_plot_basic_thumb.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/installing.md +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/providers.md +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/docs/source/style.md +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/GALLERY_HEADER.rst +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/basic/GALLERY_HEADER.rst +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/basic/plot_3d.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/basic/plot_basic.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/basic/plot_big_curves.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/basic/plot_dag.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/basic/plot_directed.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/basic/plot_grouping.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/basic/plot_house.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/basic/plot_loops.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/basic/plot_simple_path.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/GALLERY_HEADER.rst +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/data/80201010000000001.mst +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/data/GN-tree.json +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/data/breast_cancer_string_interactions_short.tsv +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/data/breast_cancer_string_network_coordinates.tsv +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/data/cell_cycle_arrest_string_interactions_short.tsv +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/data/cell_cycle_arrest_string_network_coordinates.tsv +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/data/fevo-08-588430_DataSheet1_S1.csv +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/plot_animal_phylogeny.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/plot_antibody_clone.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/plot_breast_cancer_ppi.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/plot_cell_cycle_arrest.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/plot_food_network.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/plot_foraging_table.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/plot_pollinators.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/plot_ppi.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/biology/plot_tca_cycle.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/GALLERY_HEADER.rst +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/data/chess_masters_WCC.pgn.bz2 +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/data/knuth_miles.txt.gz +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_arrowlawn.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_chess_masters.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_cliques.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_cluster_layout.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_company_structure.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_complex.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_financial_network.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_knuth_miles.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_labels_and_colors.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_max_bipartite_matching.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_minimum_spanning_trees.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_multipartite_layout.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_parallel_igraph_networkx.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_redblack.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_shortest_path.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_simple_networkx.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_social_network_circles.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_traveling_salesman.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/network_science/plot_with_colorbar.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/other/GALLERY_HEADER.rst +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/other/plot_animation.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/other/plot_edit_artists.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/other/plot_feedbacks.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/other/plot_graph.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/other/plot_mouse_hover.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/other/plot_train.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/GALLERY_HEADER.rst +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_arrows.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_depthshade.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_edgepadding.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_elements.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_four_grids.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_halfarrows.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_multistyle.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_ports.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_style.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_tension.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_vertexmarkers.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_voronoi.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/style/plot_waypoints.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/GALLERY_HEADER.rst +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/data/tree-with-support.json +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_angular_waypoints.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_biopython_tree.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_cladeedges.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_cogent3_layouts.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_cogent3_tree.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_dendropy.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_elements_tree.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_ete4.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_leafedges.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_leafedges_and_cascades.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_scalebar.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_skbio_tree.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_split_edges.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_style_tree.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_support.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_tree_node_background.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_tree_style_clades.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/tree/plot_trees_of_trees.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/zero_dependency/GALLERY_HEADER.rst +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/zero_dependency/plot_simplenetworkdataprovider.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/gallery/zero_dependency/plot_simpletreedataprovider.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/__init__.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/art3d/edge/__init__.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/art3d/edge/arrow.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/art3d/edge/geometry.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/art3d/vertex.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/artists.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/edge/__init__.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/edge/arrow.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/edge/geometry.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/edge/leaf.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/edge/ports.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/__init__.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/heuristics.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/providers/network/igraph.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/providers/network/networkx.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/providers/network/simple.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/providers/tree/biopython.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/providers/tree/cogent3.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/providers/tree/dendropy.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/providers/tree/ete4.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/providers/tree/simple.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/providers/tree/skbio.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/ingest/typing.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/label.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/network/__init__.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/network/groups.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/plotting.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/style/__init__.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/style/leaf_info.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/style/library.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/tree/cascades.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/typing.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/utils/geometry.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/utils/internal.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/utils/matplotlib.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/utils/style.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/iplotx/vertex.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/pyproject.toml +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/scripts/copy_github_release_into_version.sh +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/scripts/make_banner.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/scripts/update_pylint_badge.sh +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_biopython/cascades.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_biopython/directed_child.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_biopython/leaf_labels.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_biopython/leaf_labels_hmargin.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_biopython/leafedges.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_biopython/show_support.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_biopython/tree_basic.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_biopython/tree_radial.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_cogent3/leaf_labels.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_cogent3/leaf_labels_hmargin.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_cogent3/tree_basic.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_cogent3/tree_radial.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_dendropy/cascades.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_dendropy/directed_child.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_dendropy/leaf_labels.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_dendropy/leaf_labels_hmargin.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_dendropy/leafedges.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_dendropy/tree_basic.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_dendropy/tree_radial.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_ete4/leaf_labels.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_ete4/leaf_labels_hmargin.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_ete4/split_edges.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_ete4/tree_basic.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_ete4/tree_radial.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/clustering_directed.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/clustering_directed_large.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/graph_basic.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/graph_directed.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/graph_directed_curved_loops.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/graph_edit_children.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/graph_labels.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/graph_layout_attribute.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/graph_null.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/graph_squares_directed.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/graph_vertexsize.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/graph_with_curved_edges.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/igraph_layout_object.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph/multigraph_with_curved_edges_undirected.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph_3d/directed.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph_3d/undirected.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_igraph_3d/vertex_labels.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/cluster-layout.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/complex.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/complex_rotatelabels.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/directed_graph.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/directed_graph_with_colorbar.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/empty_graph.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/flat_style.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/house_with_colors.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/labels_and_colors.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/shortest_path.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_networkx/simple_graph.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_simple_network_provider/graph_basic.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_simple_network_provider/graph_directed.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_simple_network_provider/graph_labels.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_skbio/leaf_labels.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_skbio/leaf_labels_hmargin.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_skbio/tree_basic.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/baseline_images/test_skbio/tree_radial.png +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_arrows.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_biopython.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_cascades.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_cogent3.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_dendropy.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_edge.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_edge_geometry.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_ete4.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_geometry.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_heuristics.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_igraph.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_igraph_3d.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_ingest_protocols.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_matplotlib_utils.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_network_hotload.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_networkx.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_ports.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_simple_network_provider.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_simple_tree_provider.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_skbio.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_style.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/test_vertex.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/tests/utils.py +0 -0
- {iplotx-1.0.0 → iplotx-1.1.0}/uv.lock +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
|
|
3
|
+
|
|
4
|
+
name: Python package
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
[push, pull_request]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v5
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: ${{ matrix.python-version }}
|
|
29
|
+
|
|
30
|
+
- name: Install the project
|
|
31
|
+
run: uv sync --all-extras --group test
|
|
32
|
+
|
|
33
|
+
- name: Run pytest
|
|
34
|
+
run: uv run pytest --cov-report term-missing --cov=iplotx tests
|
|
35
|
+
|
|
36
|
+
- name: Coveralls
|
|
37
|
+
uses: coverallsapp/github-action@v2
|
|
38
|
+
with:
|
|
39
|
+
fail-on-error: false
|
|
40
|
+
|
|
41
|
+
- name: Run flake8
|
|
42
|
+
run: uv run flake8 iplotx --count --exit-zero --max-complexity=20 --max-line-length=127 --statistics
|
|
43
|
+
|
|
44
|
+
build_graph_tool:
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
strategy:
|
|
47
|
+
fail-fast: false
|
|
48
|
+
matrix:
|
|
49
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
50
|
+
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v5
|
|
53
|
+
|
|
54
|
+
- uses: conda-incubator/setup-miniconda@v3
|
|
55
|
+
with:
|
|
56
|
+
auto-activate-base: false
|
|
57
|
+
auto-update-conda: true
|
|
58
|
+
python-version: ${{ matrix.python-version }}
|
|
59
|
+
activate-environment: gt
|
|
60
|
+
miniforge-version: latest
|
|
61
|
+
channels: conda-forge
|
|
62
|
+
conda-remove-defaults: true
|
|
63
|
+
- name: Conda info
|
|
64
|
+
shell: bash -el {0}
|
|
65
|
+
run: conda info
|
|
66
|
+
- name: Conda list
|
|
67
|
+
shell: bash -el {0}
|
|
68
|
+
run: conda list
|
|
69
|
+
- name: Install graph-tool
|
|
70
|
+
shell: bash -el {0}
|
|
71
|
+
run: conda install -c conda-forge graph-tool
|
|
72
|
+
- name: Install pip
|
|
73
|
+
shell: bash -el {0}
|
|
74
|
+
run: conda install -c conda-forge pip
|
|
75
|
+
- name: Upgrade pip to >= 25.1 (which has dependency groups)
|
|
76
|
+
shell: bash -el {0}
|
|
77
|
+
run: pip install --upgrade pip
|
|
78
|
+
- name: Install deps and package
|
|
79
|
+
shell: bash -el {0}
|
|
80
|
+
run: pip install --group test .
|
|
81
|
+
- name: Check pytest
|
|
82
|
+
shell: bash -el {0}
|
|
83
|
+
run: which pytest
|
|
84
|
+
- name: Run pytest (graph-tool)
|
|
85
|
+
shell: bash -el {0}
|
|
86
|
+
run: pytest tests/test_graph_tool.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iplotx
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.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
|
|
@@ -53,14 +53,15 @@ Supports:
|
|
|
53
53
|
- **networks**:
|
|
54
54
|
- [networkx](https://networkx.org/)
|
|
55
55
|
- [igraph](igraph.readthedocs.io/)
|
|
56
|
-
- [
|
|
56
|
+
- [graph-tool](https://graph-tool.skewed.de/)
|
|
57
|
+
- [zero-dependency](https://iplotx.readthedocs.io/en/latest/gallery/plot_simplenetworkdataprovider.html#sphx-glr-gallery-plot-simplenetworkdataprovider-py)
|
|
57
58
|
- **trees**:
|
|
58
59
|
- [ETE4](https://etetoolkit.github.io/ete/)
|
|
59
60
|
- [cogent3](https://cogent3.org/)
|
|
60
61
|
- [Biopython](https://biopython.org/)
|
|
61
62
|
- [scikit-bio](https://scikit.bio)
|
|
62
63
|
- [dendropy](https://jeetsukumaran.github.io/DendroPy/index.html)
|
|
63
|
-
- [
|
|
64
|
+
- [zero-dependency](https://iplotx.readthedocs.io/en/latest/gallery/tree/plot_simpletreedataprovider.html#sphx-glr-gallery-tree-plot-simpletreedataprovider-py)
|
|
64
65
|
|
|
65
66
|
In addition to the above, *any* network or tree analysis library can register an [entry point](https://iplotx.readthedocs.io/en/latest/providers.html#creating-a-custom-data-provider) to gain compatibility with `iplotx` with no intervention from our side.
|
|
66
67
|
|
|
@@ -81,7 +82,7 @@ fig, ax = plt.subplots(figsize=(3, 3))
|
|
|
81
82
|
ipx.plot(g, ax=ax, layout=layout)
|
|
82
83
|
```
|
|
83
84
|
|
|
84
|
-

|
|
85
|
+

|
|
85
86
|
|
|
86
87
|
## Documentation
|
|
87
88
|
See [readthedocs](https://iplotx.readthedocs.io/en/latest/) for the full documentation.
|
|
@@ -90,11 +91,11 @@ See [readthedocs](https://iplotx.readthedocs.io/en/latest/) for the full documen
|
|
|
90
91
|
See [gallery](https://iplotx.readthedocs.io/en/latest/gallery/index.html).
|
|
91
92
|
|
|
92
93
|
## Features
|
|
93
|
-
- Plot networks from multiple libraries including networkx and
|
|
94
|
+
- Plot networks from multiple libraries including networkx, igraph and graph-tool, using Matplotlib. ✅
|
|
94
95
|
- Plot trees from multiple libraries such as cogent3, ETE4, skbio, biopython, and dendropy. ✅
|
|
95
96
|
- Flexible yet easy styling, including an internal library of styles ✅
|
|
96
97
|
- Interactive plotting, e.g. zooming and panning after the plot is created. ✅
|
|
97
|
-
- Store the plot to disk
|
|
98
|
+
- Store the plot to disk in many formats (SVG, PNG, PDF, GIF, etc.). ✅
|
|
98
99
|
- 3D network visualisation with depth shading. ✅
|
|
99
100
|
- Efficient plotting of large graphs (up to ~1 million nodes on a laptop). ✅
|
|
100
101
|
- Edit plotting elements after the plot is created, e.g. changing node colors, labels, etc. ✅
|
|
@@ -15,14 +15,15 @@ Supports:
|
|
|
15
15
|
- **networks**:
|
|
16
16
|
- [networkx](https://networkx.org/)
|
|
17
17
|
- [igraph](igraph.readthedocs.io/)
|
|
18
|
-
- [
|
|
18
|
+
- [graph-tool](https://graph-tool.skewed.de/)
|
|
19
|
+
- [zero-dependency](https://iplotx.readthedocs.io/en/latest/gallery/plot_simplenetworkdataprovider.html#sphx-glr-gallery-plot-simplenetworkdataprovider-py)
|
|
19
20
|
- **trees**:
|
|
20
21
|
- [ETE4](https://etetoolkit.github.io/ete/)
|
|
21
22
|
- [cogent3](https://cogent3.org/)
|
|
22
23
|
- [Biopython](https://biopython.org/)
|
|
23
24
|
- [scikit-bio](https://scikit.bio)
|
|
24
25
|
- [dendropy](https://jeetsukumaran.github.io/DendroPy/index.html)
|
|
25
|
-
- [
|
|
26
|
+
- [zero-dependency](https://iplotx.readthedocs.io/en/latest/gallery/tree/plot_simpletreedataprovider.html#sphx-glr-gallery-tree-plot-simpletreedataprovider-py)
|
|
26
27
|
|
|
27
28
|
In addition to the above, *any* network or tree analysis library can register an [entry point](https://iplotx.readthedocs.io/en/latest/providers.html#creating-a-custom-data-provider) to gain compatibility with `iplotx` with no intervention from our side.
|
|
28
29
|
|
|
@@ -43,7 +44,7 @@ fig, ax = plt.subplots(figsize=(3, 3))
|
|
|
43
44
|
ipx.plot(g, ax=ax, layout=layout)
|
|
44
45
|
```
|
|
45
46
|
|
|
46
|
-

|
|
47
|
+

|
|
47
48
|
|
|
48
49
|
## Documentation
|
|
49
50
|
See [readthedocs](https://iplotx.readthedocs.io/en/latest/) for the full documentation.
|
|
@@ -52,11 +53,11 @@ See [readthedocs](https://iplotx.readthedocs.io/en/latest/) for the full documen
|
|
|
52
53
|
See [gallery](https://iplotx.readthedocs.io/en/latest/gallery/index.html).
|
|
53
54
|
|
|
54
55
|
## Features
|
|
55
|
-
- Plot networks from multiple libraries including networkx and
|
|
56
|
+
- Plot networks from multiple libraries including networkx, igraph and graph-tool, using Matplotlib. ✅
|
|
56
57
|
- Plot trees from multiple libraries such as cogent3, ETE4, skbio, biopython, and dendropy. ✅
|
|
57
58
|
- Flexible yet easy styling, including an internal library of styles ✅
|
|
58
59
|
- Interactive plotting, e.g. zooming and panning after the plot is created. ✅
|
|
59
|
-
- Store the plot to disk
|
|
60
|
+
- Store the plot to disk in many formats (SVG, PNG, PDF, GIF, etc.). ✅
|
|
60
61
|
- 3D network visualisation with depth shading. ✅
|
|
61
62
|
- Efficient plotting of large graphs (up to ~1 million nodes on a laptop). ✅
|
|
62
63
|
- Edit plotting elements after the plot is created, e.g. changing node colors, labels, etc. ✅
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
:::
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
[iplotx](https://github.com/fabilab/iplotx) is a Python library to display graphs/networks and trees with [matplotlib](https://matplotlib.org/). It natively supports [networkx](https://networkx.org/)
|
|
20
|
+
[iplotx](https://github.com/fabilab/iplotx) is a Python library to display graphs/networks and trees with [matplotlib](https://matplotlib.org/). It natively supports [networkx](https://networkx.org/), [igraph](https://python.igraph.org/), and [graph-tool](https://graph-tool.skewed.de/) networks and [biopython](https://biopython.org/), [scikit-bio](https://scikit.bio/), [cogent3](https://cogent3.org/), [ETE4](https://etetoolkit.github.io/ete/), and [dendropy](https://jeetsukumaran.github.io/DendroPy/index.html) trees. It can also plot networks and trees from simple Python data structures for zero-dependency visualisation.
|
|
21
21
|
|
|
22
22
|
`iplotx` guarantees the **exact same visual appearance** independently of what library you used to construct the network/tree.
|
|
23
23
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Computation times
|
|
8
8
|
=================
|
|
9
|
-
**00:00.
|
|
9
|
+
**00:00.542** total execution time for 77 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_double_tree.py` (``../../gallery/tree/plot_double_tree.py``)
|
|
36
|
+
- 00:00.542
|
|
37
37
|
- 0.0
|
|
38
38
|
* - :ref:`sphx_glr_gallery_basic_plot_3d.py` (``../../gallery/basic/plot_3d.py``)
|
|
39
39
|
- 00:00.000
|
|
@@ -233,6 +233,9 @@ Computation times
|
|
|
233
233
|
* - :ref:`sphx_glr_gallery_tree_plot_leafedges_and_cascades.py` (``../../gallery/tree/plot_leafedges_and_cascades.py``)
|
|
234
234
|
- 00:00.000
|
|
235
235
|
- 0.0
|
|
236
|
+
* - :ref:`sphx_glr_gallery_tree_plot_scalebar.py` (``../../gallery/tree/plot_scalebar.py``)
|
|
237
|
+
- 00:00.000
|
|
238
|
+
- 0.0
|
|
236
239
|
* - :ref:`sphx_glr_gallery_tree_plot_skbio_tree.py` (``../../gallery/tree/plot_skbio_tree.py``)
|
|
237
240
|
- 00:00.000
|
|
238
241
|
- 0.0
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Double tree
|
|
3
|
+
===========
|
|
4
|
+
|
|
5
|
+
This example shows how to use `iplotx` to plot two trees facing each other, which is typical in coevolutionary studies.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from ete4 import Tree
|
|
9
|
+
from matplotlib import pyplot as plt
|
|
10
|
+
import iplotx as ipx
|
|
11
|
+
|
|
12
|
+
tree1 = Tree(
|
|
13
|
+
"((),((),(((),()),((),()))));",
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
tree2 = Tree(
|
|
18
|
+
"((),((),(),((),())),());",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
fig, ax = plt = plt.subplots(figsize=(9, 4))
|
|
22
|
+
|
|
23
|
+
# Plot first tree on the left
|
|
24
|
+
ipx.plotting.tree(
|
|
25
|
+
tree1,
|
|
26
|
+
ax=ax,
|
|
27
|
+
aspect=1,
|
|
28
|
+
edge_color="tomato",
|
|
29
|
+
leaf_deep=True,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Plot second tree on the right, facing left
|
|
33
|
+
ipx.plotting.tree(
|
|
34
|
+
tree2,
|
|
35
|
+
ax=ax,
|
|
36
|
+
aspect=1,
|
|
37
|
+
edge_color="steelblue",
|
|
38
|
+
layout="horizontal",
|
|
39
|
+
layout_orientation="left",
|
|
40
|
+
layout_start=(11, 0),
|
|
41
|
+
leaf_deep=True,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Add lines connecting corresponding leaves
|
|
45
|
+
matches = [
|
|
46
|
+
(0, 0),
|
|
47
|
+
(1, 4),
|
|
48
|
+
(2, 5),
|
|
49
|
+
(3, 2),
|
|
50
|
+
(4, 1),
|
|
51
|
+
(5, 5),
|
|
52
|
+
]
|
|
53
|
+
for y1, y2 in matches:
|
|
54
|
+
ax.plot(
|
|
55
|
+
[5.2, 6.8], [y1, y2], color="gray", linewidth=2,
|
|
56
|
+
)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from typing import (
|
|
2
|
+
Optional,
|
|
3
|
+
Sequence,
|
|
4
|
+
)
|
|
5
|
+
from collections.abc import Hashable
|
|
6
|
+
import importlib
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
|
|
10
|
+
from ....typing import (
|
|
11
|
+
LayoutType,
|
|
12
|
+
)
|
|
13
|
+
from ...heuristics import (
|
|
14
|
+
normalise_layout,
|
|
15
|
+
)
|
|
16
|
+
from ...typing import (
|
|
17
|
+
NetworkDataProvider,
|
|
18
|
+
NetworkData,
|
|
19
|
+
)
|
|
20
|
+
from ....utils.internal import (
|
|
21
|
+
_make_layout_columns,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class GraphToolDataProvider(NetworkDataProvider):
|
|
26
|
+
def __call__(
|
|
27
|
+
self,
|
|
28
|
+
layout: Optional[LayoutType] = None,
|
|
29
|
+
vertex_labels: Optional[Sequence[str] | dict[Hashable, str] | pd.Series] = None,
|
|
30
|
+
edge_labels: Optional[Sequence[str] | dict[str]] = None,
|
|
31
|
+
) -> NetworkData:
|
|
32
|
+
"""Create network data object for iplotx from an igraph object."""
|
|
33
|
+
|
|
34
|
+
# Get layout
|
|
35
|
+
vertex_df = normalise_layout(
|
|
36
|
+
layout,
|
|
37
|
+
network=self.network,
|
|
38
|
+
nvertices=self.number_of_vertices(),
|
|
39
|
+
)
|
|
40
|
+
ndim = vertex_df.shape[1]
|
|
41
|
+
vertex_df.columns = _make_layout_columns(ndim)
|
|
42
|
+
|
|
43
|
+
# Vertices are ordered integers, no gaps
|
|
44
|
+
|
|
45
|
+
# Vertex labels
|
|
46
|
+
# Recast vertex_labels=False as vertex_labels=None
|
|
47
|
+
if np.isscalar(vertex_labels) and (not vertex_labels):
|
|
48
|
+
vertex_labels = None
|
|
49
|
+
if vertex_labels is not None:
|
|
50
|
+
if np.isscalar(vertex_labels):
|
|
51
|
+
vertex_df["label"] = vertex_df.index.astype(str)
|
|
52
|
+
elif len(vertex_labels) != len(vertex_df):
|
|
53
|
+
raise ValueError("Vertex labels must be the same length as the number of vertices.")
|
|
54
|
+
else:
|
|
55
|
+
vertex_df["label"] = vertex_labels
|
|
56
|
+
|
|
57
|
+
# Edges are a list of tuples, because of multiedges
|
|
58
|
+
tmp = []
|
|
59
|
+
for edge in self.network.edges():
|
|
60
|
+
row = {"_ipx_source": edge.source(), "_ipx_target": edge.target()}
|
|
61
|
+
# TODO: add graph-tool edge attributes
|
|
62
|
+
# row.update(edge.attributes())
|
|
63
|
+
tmp.append(row)
|
|
64
|
+
if len(tmp):
|
|
65
|
+
edge_df = pd.DataFrame(tmp)
|
|
66
|
+
else:
|
|
67
|
+
edge_df = pd.DataFrame(columns=["_ipx_source", "_ipx_target"])
|
|
68
|
+
del tmp
|
|
69
|
+
|
|
70
|
+
# Edge labels
|
|
71
|
+
if edge_labels is not None:
|
|
72
|
+
if len(edge_labels) != len(edge_df):
|
|
73
|
+
raise ValueError("Edge labels must be the same length as the number of edges.")
|
|
74
|
+
edge_df["label"] = edge_labels
|
|
75
|
+
|
|
76
|
+
network_data = {
|
|
77
|
+
"vertex_df": vertex_df,
|
|
78
|
+
"edge_df": edge_df,
|
|
79
|
+
"directed": self.is_directed(),
|
|
80
|
+
"ndim": ndim,
|
|
81
|
+
}
|
|
82
|
+
return network_data
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def check_dependencies() -> bool:
|
|
86
|
+
return importlib.util.find_spec("graph_tool") is not None
|
|
87
|
+
|
|
88
|
+
@staticmethod
|
|
89
|
+
def graph_type():
|
|
90
|
+
import graph_tool.all as gt
|
|
91
|
+
|
|
92
|
+
return gt.Graph
|
|
93
|
+
|
|
94
|
+
def is_directed(self):
|
|
95
|
+
"""Whether the network is directed."""
|
|
96
|
+
return self.network.is_directed()
|
|
97
|
+
|
|
98
|
+
def number_of_vertices(self):
|
|
99
|
+
"""The number of vertices/nodes in the network."""
|
|
100
|
+
return self.network.num_vertices()
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
Layout functions, currently limited to trees.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import (
|
|
6
|
+
Any,
|
|
7
|
+
Optional,
|
|
8
|
+
)
|
|
6
9
|
from collections.abc import (
|
|
7
10
|
Hashable,
|
|
8
11
|
Callable,
|
|
@@ -99,6 +102,8 @@ def _horizontal_tree_layout_right(
|
|
|
99
102
|
|
|
100
103
|
def _horizontal_tree_layout(
|
|
101
104
|
orientation="right",
|
|
105
|
+
start: tuple[float, float] = (0, 0),
|
|
106
|
+
span: Optional[float] = None,
|
|
102
107
|
**kwargs,
|
|
103
108
|
) -> dict[Hashable, list[float]]:
|
|
104
109
|
"""Horizontal tree layout."""
|
|
@@ -110,11 +115,24 @@ def _horizontal_tree_layout(
|
|
|
110
115
|
if orientation == "left":
|
|
111
116
|
for key in layout:
|
|
112
117
|
layout[key][0] *= -1
|
|
118
|
+
|
|
119
|
+
if span is not None:
|
|
120
|
+
cur_span = len(layout) - 1
|
|
121
|
+
for key in layout:
|
|
122
|
+
layout[key][1] = float(layout[key][1]) * span / cur_span
|
|
123
|
+
|
|
124
|
+
if start != (0, 0):
|
|
125
|
+
for key in layout:
|
|
126
|
+
layout[key][0] += start[0]
|
|
127
|
+
layout[key][1] += start[1]
|
|
128
|
+
|
|
113
129
|
return layout
|
|
114
130
|
|
|
115
131
|
|
|
116
132
|
def _vertical_tree_layout(
|
|
117
133
|
orientation="descending",
|
|
134
|
+
start: tuple[float, float] = (0, 0),
|
|
135
|
+
span: Optional[float] = None,
|
|
118
136
|
**kwargs,
|
|
119
137
|
) -> dict[Hashable, list[float]]:
|
|
120
138
|
"""Vertical tree layout."""
|
|
@@ -125,6 +143,17 @@ def _vertical_tree_layout(
|
|
|
125
143
|
layout[key] = value[::-1]
|
|
126
144
|
# Orient vertically
|
|
127
145
|
layout[key][1] *= sign
|
|
146
|
+
|
|
147
|
+
if span is not None:
|
|
148
|
+
cur_span = len(layout) - 1
|
|
149
|
+
for key in layout:
|
|
150
|
+
layout[key][0] = float(layout[key][0]) * span / cur_span
|
|
151
|
+
|
|
152
|
+
if start != (0, 0):
|
|
153
|
+
for key in layout:
|
|
154
|
+
layout[key][0] += start[0]
|
|
155
|
+
layout[key][1] += start[1]
|
|
156
|
+
|
|
128
157
|
return layout
|
|
129
158
|
|
|
130
159
|
|
|
@@ -669,6 +669,7 @@ class TreeArtist(mpl.artist.Artist):
|
|
|
669
669
|
def scalebar(
|
|
670
670
|
self,
|
|
671
671
|
loc: str = "upper left",
|
|
672
|
+
label_format: str = ".2f",
|
|
672
673
|
**kwargs,
|
|
673
674
|
):
|
|
674
675
|
"""Create scalebar for the tree.
|
|
@@ -689,6 +690,8 @@ class TreeArtist(mpl.artist.Artist):
|
|
|
689
690
|
self,
|
|
690
691
|
layout=self.get_layout_name(),
|
|
691
692
|
loc=loc,
|
|
693
|
+
label_format=label_format,
|
|
694
|
+
**kwargs,
|
|
692
695
|
)
|
|
693
696
|
|
|
694
697
|
# Remove previous scalebars if any
|
|
@@ -37,13 +37,15 @@ class TreeScalebarArtist(Legend):
|
|
|
37
37
|
self,
|
|
38
38
|
treeartist,
|
|
39
39
|
layout: str = "horizontal",
|
|
40
|
-
frameon=False,
|
|
40
|
+
frameon: bool = False,
|
|
41
|
+
label_format: str = ".2f",
|
|
41
42
|
**kwargs,
|
|
42
43
|
):
|
|
43
44
|
handles = [treeartist.get_edges()]
|
|
44
45
|
labels = [""]
|
|
45
46
|
self._layout = layout
|
|
46
47
|
self._treeartist = treeartist
|
|
48
|
+
self._label_format = label_format
|
|
47
49
|
|
|
48
50
|
if layout == "vertical":
|
|
49
51
|
handler_kwargs = dict(xerr_size=0, yerr_size=1)
|
|
@@ -191,13 +193,12 @@ class TreeScalebarArtist(Legend):
|
|
|
191
193
|
|
|
192
194
|
bar_trans = bar_handle.get_transform()
|
|
193
195
|
data_trans = self.parent.transData
|
|
194
|
-
# FIXME: this is off, probably because of some Packer anchor additional transform
|
|
195
196
|
composite_trans = data_trans.inverted() + bar_trans
|
|
196
197
|
|
|
197
198
|
p0_data = composite_trans.transform(p0)
|
|
198
199
|
p1_data = composite_trans.transform(p1)
|
|
199
200
|
distance = np.linalg.norm(p1_data - p0_data)
|
|
200
|
-
label =
|
|
201
|
+
label = format(distance, self._label_format)
|
|
201
202
|
return label
|
|
202
203
|
|
|
203
204
|
def draw(self, renderer):
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
../test_igraph/graph_basic.png
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
../test_igraph/graph_directed.png
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import matplotlib as mpl
|
|
3
|
+
|
|
4
|
+
mpl.use("agg")
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
import iplotx as ipx
|
|
7
|
+
|
|
8
|
+
from utils import image_comparison
|
|
9
|
+
|
|
10
|
+
gt = pytest.importorskip("graph_tool")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def layout_small_ring():
|
|
15
|
+
coords = [
|
|
16
|
+
[1.015318095035966, 0.03435580194714975],
|
|
17
|
+
[0.29010409851547664, 1.0184451153265959],
|
|
18
|
+
[-0.8699239050738742, 0.6328259400443561],
|
|
19
|
+
[-0.8616466426732888, -0.5895891303732176],
|
|
20
|
+
[0.30349699041342515, -0.9594640169691343],
|
|
21
|
+
]
|
|
22
|
+
return coords
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@image_comparison(baseline_images=["graph_basic"], remove_text=True)
|
|
26
|
+
def test_basic(layout_small_ring):
|
|
27
|
+
g = gt.Graph(directed=False)
|
|
28
|
+
vertices = list(g.add_vertex(5))
|
|
29
|
+
for i in range(5):
|
|
30
|
+
g.add_edge(vertices[i], vertices[(i + 1) % 5])
|
|
31
|
+
|
|
32
|
+
fig, ax = plt.subplots(figsize=(3, 3))
|
|
33
|
+
ipx.graph(g, ax=ax, layout=layout_small_ring)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@image_comparison(baseline_images=["graph_directed"], remove_text=True)
|
|
37
|
+
def test_directed(layout_small_ring):
|
|
38
|
+
g = gt.Graph(directed=True)
|
|
39
|
+
vertices = list(g.add_vertex(5))
|
|
40
|
+
for i in range(5):
|
|
41
|
+
g.add_edge(vertices[i], vertices[(i + 1) % 5])
|
|
42
|
+
|
|
43
|
+
fig, ax = plt.subplots(figsize=(3, 3))
|
|
44
|
+
ipx.graph(g, ax=ax, layout=layout_small_ring)
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
|
2
|
-
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
|
|
3
|
-
|
|
4
|
-
name: Python package
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
[push, pull_request]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
build:
|
|
11
|
-
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
strategy:
|
|
14
|
-
fail-fast: false
|
|
15
|
-
matrix:
|
|
16
|
-
python-version: ["3.11", "3.12", "3.13"]
|
|
17
|
-
|
|
18
|
-
steps:
|
|
19
|
-
- uses: actions/checkout@v4
|
|
20
|
-
|
|
21
|
-
- name: Install uv
|
|
22
|
-
uses: astral-sh/setup-uv@v5
|
|
23
|
-
with:
|
|
24
|
-
python-version: ${{ matrix.python-version }}
|
|
25
|
-
|
|
26
|
-
- name: Set up Python ${{ matrix.python-version }}
|
|
27
|
-
uses: actions/setup-python@v5
|
|
28
|
-
with:
|
|
29
|
-
python-version: ${{ matrix.python-version }}
|
|
30
|
-
|
|
31
|
-
- name: Install the project
|
|
32
|
-
run: uv sync --all-extras --group test
|
|
33
|
-
|
|
34
|
-
- name: Run pytest
|
|
35
|
-
run: uv run pytest --cov-report term-missing --cov=iplotx tests
|
|
36
|
-
|
|
37
|
-
- name: Coveralls
|
|
38
|
-
uses: coverallsapp/github-action@v2
|
|
39
|
-
with:
|
|
40
|
-
fail-on-error: false
|
|
41
|
-
|
|
42
|
-
- name: Run flake8
|
|
43
|
-
run: uv run flake8 iplotx --count --exit-zero --max-complexity=20 --max-line-length=127 --statistics
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|