Library for the Development and Use of Phylogenetic Network Methods
The NetworkMoves module provides functions for modifying phylogenetic networks, including adding/removing reticulations, performing NNI operations, and changing node heights. These are the core operations used in network search algorithms.
The four network moves implemented are:
Add a hybrid (reticulation) edge from source to destination. Modifies the network in place.
Before: After:
src: dest: src: dest:
a x a x
| | | |
| | | |
v v v v
b y n1- - - - - ->n2
| |
v v
b y
| Parameter | Type | Description |
|---|---|---|
| net | Network | Network to modify |
| source | Edge | Origin edge for hybrid |
| destination | Edge | Target edge for hybrid |
| t_src | float | Speciation time at n1 (optional) |
| t_dest | float | Speciation time at n2 (optional) |
If source == destination, a bubble edge (parallel edges) will be created with gamma=0.5 on both edges.
Remove a hybrid edge from the network. Modifies the network in place.
Before: After:
src: dest: src: dest:
a x a x
| | | |
v v v v
n1- - - - - ->n2 b y
| |
v v
b y
| Parameter | Type | Description |
|---|---|---|
| net | Network | Network to modify |
| hybrid_edge | Edge | Edge whose dest is a reticulation node |
Exception - If edge destination is not a reticulation, or if
edge source is a reticulation
Perform a Nearest Neighbor Interchange (NNI) on the network. Selects a random internal edge and swaps subtrees. Modifies the network in place.
Before: After (one option):
a a
/ \ / \
c b d b
/ \ / \
d e c e
| Parameter | Type | Description |
|---|---|---|
| net | Network | Network to modify |
Exception - If no internal edges available or not enough
neighbors for NNI
Change the height (speciation time) of a node without altering surrounding node heights. Modifies the network in place.
| Parameter | Type | Description |
|---|---|---|
| n | Node | Node to modify |
| net | Network | Network containing the node |
| height | float | New height for the node |
| extend | bool | If True, retain subtree branch lengths |
The new height must satisfy: min(child heights) < new_height < max(parent heights)
NetworkError - If new height is out of bounds or node lacks
parents/children
from PhyNetPy.NetworkMoves import add_hybrid, remove_hybrid, nni, node_height_change
from PhyNetPy.NetworkParser import NetworkParser
# Load a network
parser = NetworkParser("tree.nex")
net = parser.get_network(0)
# Add a hybrid edge between two edges
edges = list(net.E())
source_edge = edges[0]
dest_edge = edges[2]
add_hybrid(net, source_edge, dest_edge)
# Remove a hybrid edge
hybrid_edges = [e for e in net.E() if e.dest.is_reticulation()]
if hybrid_edges:
remove_hybrid(net, hybrid_edges[0])
# Perform NNI
try:
nni(net)
except Exception as e:
print(f"NNI failed: {e}")
# Change node height
internal_nodes = [n for n in net.V() if n not in net.get_leaves() and n != net.root()]
if internal_nodes:
node = internal_nodes[0]
current_height = node.get_time()
new_height = current_height + 0.1
try:
node_height_change(node, net, new_height)
except Exception as e:
print(f"Height change failed: {e}")
# Create a bubble (genome duplication)
edge = edges[0]
add_hybrid(net, edge, edge) # Same edge = bubble