Module treespace_metrics.jetten
Expand source code
import networkx as nx
from networkx import get_node_attributes, DiGraph, Graph
import platform
from treespace_metrics.utils import maximum_matching_all, is_omnian, is_reticulation
from treespace_metrics.drawing import draw_bipartite
plt = platform.system()
def is_tree_based(network: DiGraph, name=None, draw=False) -> bool:
"""
Read the paper "Nonbinary tree-based phylogenetic networks' by Laura Jetten and Leo van Iersel".
The complete algorithm that checks if a network is tree-based.
Args:
network (DiGraph): Input phylogenetic network N.
name (str, optional): The name of the graph, used to save output images of the network. Defaults to None.
draw (bool, optional): Whether to draw the bipartite graph. Defaults to False.
Returns:
bool: True if the network is tree-based, False otherwise.
"""
jetten_bipartite_network = jetten_bipartite(network)
unmatched_omnian = jetten_network(jetten_bipartite_network, name, draw)
return len(unmatched_omnian) == 0
def jetten_bipartite(network: DiGraph) -> Graph:
"""
Read the paper "Nonbinary tree-based phylogenetic networks' by Laura Jetten and Leo van Iersel".
Take an input phylogenetic network N and build the bipartite graph used by Jetten et al.
Args:
network (DiGraph): The input phylogenetic network.
Returns:
Graph: A bipartite graph which will be used for the next step of the algorithm.
"""
jetten = Graph()
omnians = []
reticulation = []
# Fill the nodes up
for node in network.nodes():
# set Reticulations
if is_reticulation(network, node):
reticulation.append(node)
jetten.add_node('R-' + node, biparite=1)
# set Omnians
if is_omnian(network, node):
omnians.append(node)
jetten.add_node(node, biparite=0)
data = get_node_attributes(jetten, 'biparite')
for source_node, target_node in network.edges():
try:
# source_node is an omnian vertex
if data[source_node] == 0:
jetten.add_edge(source_node, 'R-' + target_node)
except KeyError:
continue
return jetten
def jetten_network(bipartite_network: Graph, name=None, draw=False) -> set:
"""
Use this function to check if the network is tree-based by completing the maximum matching.
This function will return the unmatched omnian nodes in the network from maximum matching, and also draw the bipartite graph.
Args:
bipartite_network (Graph): The bipartite graph generated from the input phylogenetic network.
name (str, optional): The name of the output file with the bipartite graph. Defaults to None.
draw (bool, optional): Whether to draw the bipartite graph. Defaults to False.
Returns:
set: The unmatched omnian nodes in the network from maximum matching.
"""
matched_omnians = set()
try:
max_match = maximum_matching_all(bipartite_network)
if draw:
if name is None:
draw_bipartite(bipartite_network, max_match, graph_name="jetten-bipartite")
else:
draw_bipartite(bipartite_network, max_match, graph_name=name + "-jetten-bipartite")
omnians = set(n for n, d in bipartite_network.nodes(data=True) if d['biparite'] == 0)
is_omnian_node = get_node_attributes(bipartite_network, 'biparite')
for source_node, target_node in max_match.items():
if is_omnian_node[source_node] == 1:
matched_omnians.add(target_node)
if is_omnian_node[target_node] == 1:
matched_omnians.add(source_node)
set_minus = omnians - matched_omnians
except nx.exception.NetworkXPointlessConcept:
return set()
return set_minus
Functions
def is_tree_based(network: networkx.classes.digraph.DiGraph, name=None, draw=False) ‑> bool
-
Read the paper "Nonbinary tree-based phylogenetic networks' by Laura Jetten and Leo van Iersel". The complete algorithm that checks if a network is tree-based.
Args
network
:DiGraph
- Input phylogenetic network N.
name
:str
, optional- The name of the graph, used to save output images of the network. Defaults to None.
draw
:bool
, optional- Whether to draw the bipartite graph. Defaults to False.
Returns
bool
- True if the network is tree-based, False otherwise.
Expand source code
def is_tree_based(network: DiGraph, name=None, draw=False) -> bool: """ Read the paper "Nonbinary tree-based phylogenetic networks' by Laura Jetten and Leo van Iersel". The complete algorithm that checks if a network is tree-based. Args: network (DiGraph): Input phylogenetic network N. name (str, optional): The name of the graph, used to save output images of the network. Defaults to None. draw (bool, optional): Whether to draw the bipartite graph. Defaults to False. Returns: bool: True if the network is tree-based, False otherwise. """ jetten_bipartite_network = jetten_bipartite(network) unmatched_omnian = jetten_network(jetten_bipartite_network, name, draw) return len(unmatched_omnian) == 0
def jetten_bipartite(network: networkx.classes.digraph.DiGraph) ‑> networkx.classes.graph.Graph
-
Read the paper "Nonbinary tree-based phylogenetic networks' by Laura Jetten and Leo van Iersel". Take an input phylogenetic network N and build the bipartite graph used by Jetten et al.
Args
network
:DiGraph
- The input phylogenetic network.
Returns
Graph
- A bipartite graph which will be used for the next step of the algorithm.
Expand source code
def jetten_bipartite(network: DiGraph) -> Graph: """ Read the paper "Nonbinary tree-based phylogenetic networks' by Laura Jetten and Leo van Iersel". Take an input phylogenetic network N and build the bipartite graph used by Jetten et al. Args: network (DiGraph): The input phylogenetic network. Returns: Graph: A bipartite graph which will be used for the next step of the algorithm. """ jetten = Graph() omnians = [] reticulation = [] # Fill the nodes up for node in network.nodes(): # set Reticulations if is_reticulation(network, node): reticulation.append(node) jetten.add_node('R-' + node, biparite=1) # set Omnians if is_omnian(network, node): omnians.append(node) jetten.add_node(node, biparite=0) data = get_node_attributes(jetten, 'biparite') for source_node, target_node in network.edges(): try: # source_node is an omnian vertex if data[source_node] == 0: jetten.add_edge(source_node, 'R-' + target_node) except KeyError: continue return jetten
def jetten_network(bipartite_network: networkx.classes.graph.Graph, name=None, draw=False) ‑> set
-
Use this function to check if the network is tree-based by completing the maximum matching. This function will return the unmatched omnian nodes in the network from maximum matching, and also draw the bipartite graph.
Args
bipartite_network
:Graph
- The bipartite graph generated from the input phylogenetic network.
name
:str
, optional- The name of the output file with the bipartite graph. Defaults to None.
draw
:bool
, optional- Whether to draw the bipartite graph. Defaults to False.
Returns
set
- The unmatched omnian nodes in the network from maximum matching.
Expand source code
def jetten_network(bipartite_network: Graph, name=None, draw=False) -> set: """ Use this function to check if the network is tree-based by completing the maximum matching. This function will return the unmatched omnian nodes in the network from maximum matching, and also draw the bipartite graph. Args: bipartite_network (Graph): The bipartite graph generated from the input phylogenetic network. name (str, optional): The name of the output file with the bipartite graph. Defaults to None. draw (bool, optional): Whether to draw the bipartite graph. Defaults to False. Returns: set: The unmatched omnian nodes in the network from maximum matching. """ matched_omnians = set() try: max_match = maximum_matching_all(bipartite_network) if draw: if name is None: draw_bipartite(bipartite_network, max_match, graph_name="jetten-bipartite") else: draw_bipartite(bipartite_network, max_match, graph_name=name + "-jetten-bipartite") omnians = set(n for n, d in bipartite_network.nodes(data=True) if d['biparite'] == 0) is_omnian_node = get_node_attributes(bipartite_network, 'biparite') for source_node, target_node in max_match.items(): if is_omnian_node[source_node] == 1: matched_omnians.add(target_node) if is_omnian_node[target_node] == 1: matched_omnians.add(source_node) set_minus = omnians - matched_omnians except nx.exception.NetworkXPointlessConcept: return set() return set_minus