← Back to PhyNetPy

PhyNetPy Documentation

Library for the Development and Use of Phylogenetic Network Methods

GraphUtils Module v1.0.0

The GraphUtils module provides utility functions for manipulating and analyzing Network objects, including tree extraction, cluster computation, network metrics, and topology operations.

Author:
Mark Kessler
Last Edit:
8/18/25
Source:
GraphUtils.py

Cluster Functions

def get_all_clusters(net: Network, node: Node = None, include_trivial: bool = False) -> set[frozenset[Node]]

Compile all clusters in a graph. For ((A, B)C, D), clusters are {(A,B), (A,B,C)}.

Parameter Type Description
net Network The network to operate on
node Node Starting point (defaults to root)
include_trivial bool Include size-1 clusters. Default False.
Returns: set[frozenset[Node]] - Set of all clusters

Tree Extraction

def get_all_subtrees(net: Network) -> list[Network]

Generate all possible trees by removing hybrid edges.

def dominant_tree(net: Network) -> Network

Generate the dominant tree by retaining only reticulation edges with highest inheritance probability.

def sample_displayed_tree(net: Network, rng: np.random.Generator = None) -> Network

Sample one displayed tree by selecting incoming edges proportional to inheritance probability.

Network Metrics

def count_reticulations(net: Network) -> int

Count reticulation nodes (indegree >= 2).

def count_displayed_trees(net: Network) -> int

Estimate number of displayed trees (product of inbound edge counts for reticulation nodes).

def level(net: Network) -> int

Compute network level (max reticulations in any biconnected component). Returns 0 for trees.

def blobs(net: Network) -> list[set[Node]]

Return biconnected components ("blobs") of the underlying undirected graph.

def is_tree(net: Network) -> bool

Check if network has no reticulation nodes.

def pairwise_leaf_distance(net: Network, use_branch_lengths: bool = True) -> dict[tuple[str, str], float]

Compute pairwise distances between leaves on the underlying undirected graph.

Validation Functions

def validate_binary(net: Network, require_tree_nodes: bool = True, require_retic_nodes: bool = True) -> tuple[bool, dict[str, list[Node]]]

Validate standard binary constraints (tree nodes: indegree=1, outdegree=2; retic nodes: indegree=2, outdegree=1).

Returns: tuple - (is_valid, violations dict)
def validate_times_and_lengths(net: Network, tol: float = 1e-5) -> tuple[bool, list[str]]

Validate consistency of node times and branch lengths.

def detect_bubbles(net: Network) -> list[tuple[Edge, Edge]]

Detect bubble structures (parallel directed edges with same endpoints).

Graph Operations

def merge_networks(left: Network, right: Network) -> Network

Combine two networks by making their roots children of a new root.

def subnet_given_leaves(net: Network, leaf_set: list[Node]) -> Network

Extract subnetwork containing only specified leaves.

def induced_subnetwork_by_taxa(net: Network, taxa: list[str]) -> Network

Construct subnetwork induced by a set of leaf labels.

def contract_edge(net: Network, edge: Edge, keep: str = "parent") -> None

Contract an internal edge by merging its endpoints (in-place).

def reroot(net: Network, new_root: Node) -> Network

Return a copy of the network re-rooted at specified node.

def transitive_reduction(net: Network) -> Network

Remove edges for which an alternate directed path exists (requires acyclic).

def break_cycles(net: Network, strategy: str = "greedy") -> Network

Produce an acyclic copy by removing cycle-forming edges.

def topological_order(net: Network) -> list[Node]

Compute topological order from roots to leaves (requires acyclic).

def ancestors_descendants(net: Network) -> tuple[dict, dict]

Compute ancestor and descendant sets for each node.

def bridges_and_articulations(net: Network) -> tuple[list, list]

Compute bridges and articulation points using Tarjan's algorithm.

Topology Functions

def extract_topology(newick_str: str) -> str

Extract topology from Newick string by removing branch lengths and metadata.

def is_isomorphic(net1: Network, net2: Network) -> bool

Check if two networks are topologically identical (ignoring labels and branch lengths).

def reticulation_parent_pairs(net: Network) -> dict[Node, list[Edge]]

Map each reticulation node to its inbound edges, sorted by gamma.

Visualization

def ascii(net: Network, show_edge_lengths: bool = False) -> str

Generate ASCII art representation of the network (root at top, leaves at bottom).

def ascii_extended(net: Network) -> str

Generate detailed ASCII art with extended connecting lines for wide trees.

Usage Examples

from PhyNetPy.GraphUtils import *
from PhyNetPy.NetworkParser import NetworkParser

# Load a network
parser = NetworkParser("network.nex")
net = parser.get_network(0)

# Get all clusters
clusters = get_all_clusters(net)
print(f"Found {len(clusters)} clusters")

# Check network level
lvl = level(net)
print(f"Network level: {lvl}")

# Count reticulations
retics = count_reticulations(net)
print(f"Reticulations: {retics}")

# Extract displayed trees
trees = get_all_subtrees(net)
print(f"Displayed trees: {len(trees)}")

# Get dominant tree
dom = dominant_tree(net)

# Validate binary structure
is_valid, violations = validate_binary(net)
if not is_valid:
    print("Violations:", violations)

# Compute pairwise distances
distances = pairwise_leaf_distance(net)

# ASCII visualization
print(ascii(net))

See Also

Navigation

Modules

This Page