Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bigtree/tree/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -1207,8 +1207,8 @@ def tree_to_newick(
Args:
tree (Node): tree to be exported
intermediate_node_name (bool): indicator if intermediate nodes have node names, defaults to True
length_attr (str): node attribute to extract into outside of bracket, optional
length_sep (str): separate between node name and length, used if length_attr is non-empty, defaults to ":"
length_attr (str): node length attribute to extract to beside name, optional
length_sep (str): separator between node name and length, used if length_attr is non-empty, defaults to ":"
attr_list (Iterable[str]): list of node attributes to extract into square bracket, optional
attr_prefix (str): prefix before all attributes, within square bracket, used if attr_list is non-empty, defaults to "&&NHX:"
attr_sep (str): separator between attributes, within square brackets, used if attr_list is non-empty, defaults to ":"
Expand Down
35 changes: 35 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,41 @@ def binarytree_node():
return a


@pytest.fixture
def phylogenetic_tree():
"""
Example taken from: https://www.cs.mcgill.ca/~birch/doc/forester/NHX.pdf
"""
root = Node("placeholder_root", E="1.1.1.1", D="N")
metazoa = Node(
"placeholder_metazoa",
length=0.1,
S="Metazoa",
E="1.1.1.1",
D="N",
parent=root,
)
primates = Node(
"placeholder_primates",
length=0.05,
S="Primates",
E="1.1.1.1",
D="Y",
B="100",
parent=metazoa,
)
_ = Node("ADH2", length=0.1, S="human", E="1.1.1.1", parent=primates)
_ = Node("ADH1", length=0.11, S="human", E="1.1.1.1", parent=primates)
_ = Node("ADHY", length=0.1, S="nematode", E="1.1.1.1", parent=metazoa)
_ = Node("ADHX", length=0.12, S="insect", E="1.1.1.1", parent=metazoa)
fungi = Node("placeholder_fungi", length=0.1, S="Fungi", parent=root)
_ = Node("ADH4", length=0.09, S="yeast", E="1.1.1.1", parent=fungi)
_ = Node("ADH3", length=0.13, S="yeast", E="1.1.1.1", parent=fungi)
_ = Node("ADH2", length=0.12, S="yeast", E="1.1.1.1", parent=fungi)
_ = Node("ADH1", length=0.11, S="yeast", E="1.1.1.1", parent=fungi)
return root


def assert_print_statement(func, expected, *args, **kwargs):
captured_output = io.StringIO()
sys.stdout = captured_output
Expand Down
59 changes: 20 additions & 39 deletions tests/tree/test_export.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import pandas as pd
import pytest

from bigtree.node.node import Node
from bigtree.tree.construct import dataframe_to_tree, dict_to_tree, nested_dict_to_tree
from bigtree.tree.export import (
print_tree,
Expand Down Expand Up @@ -1384,13 +1383,13 @@ class TestTreeToNewick:
@staticmethod
def test_tree_to_newick(tree_node):
newick_str = tree_to_newick(tree_node)
expected_str = """((d,(g,h)e)b,(f)c)a"""
expected_str = "((d,(g,h)e)b,(f)c)a"
assert newick_str == expected_str

@staticmethod
def test_tree_to_newick_length(tree_node):
newick_str = tree_to_newick(tree_node, length_attr="age")
expected_str = """((d:40,(g:10,h:6)e:35)b:65,(f:38)c:60)a"""
expected_str = "((d:40,(g:10,h:6)e:35)b:65,(f:38)c:60)a"
assert newick_str == expected_str

@staticmethod
Expand All @@ -1402,13 +1401,13 @@ def test_tree_to_newick_length_invalid_error(tree_node):
@staticmethod
def test_tree_to_newick_length_sep(tree_node):
newick_str = tree_to_newick(tree_node, length_attr="age", length_sep=";")
expected_str = """((d;40,(g;10,h;6)e;35)b;65,(f;38)c;60)a"""
expected_str = "((d;40,(g;10,h;6)e;35)b;65,(f;38)c;60)a"
assert newick_str == expected_str

@staticmethod
def test_tree_to_newick_attr_list(tree_node):
newick_str = tree_to_newick(tree_node, attr_list=["age"])
expected_str = """((d[&&NHX:age=40],(g[&&NHX:age=10],h[&&NHX:age=6])e[&&NHX:age=35])b[&&NHX:age=65],(f[&&NHX:age=38])c[&&NHX:age=60])a[&&NHX:age=90]"""
expected_str = "((d[&&NHX:age=40],(g[&&NHX:age=10],h[&&NHX:age=6])e[&&NHX:age=35])b[&&NHX:age=65],(f[&&NHX:age=38])c[&&NHX:age=60])a[&&NHX:age=90]"
assert newick_str == expected_str

@staticmethod
Expand All @@ -1420,54 +1419,36 @@ def test_tree_to_newick_attr_list_invalid(tree_node):
@staticmethod
def test_tree_to_newick_attr_prefix(tree_node):
newick_str = tree_to_newick(tree_node, attr_list=["age"], attr_prefix="")
expected_str = """((d[age=40],(g[age=10],h[age=6])e[age=35])b[age=65],(f[age=38])c[age=60])a[age=90]"""
expected_str = "((d[age=40],(g[age=10],h[age=6])e[age=35])b[age=65],(f[age=38])c[age=60])a[age=90]"
assert newick_str == expected_str

@staticmethod
def test_tree_to_newick_intermediate_node_name(tree_node):
newick_str = tree_to_newick(
tree_node, intermediate_node_name=False, attr_list=["age"]
)
expected_str = """((d[&&NHX:age=40],(g[&&NHX:age=10],h[&&NHX:age=6])[&&NHX:age=35])[&&NHX:age=65],(f[&&NHX:age=38])[&&NHX:age=60])[&&NHX:age=90]"""
expected_str = "((d[&&NHX:age=40],(g[&&NHX:age=10],h[&&NHX:age=6])[&&NHX:age=35])[&&NHX:age=65],(f[&&NHX:age=38])[&&NHX:age=60])[&&NHX:age=90]"
assert newick_str == expected_str

@staticmethod
def test_tree_to_newick_phylogenetic():
"""
Example taken from: https://www.cs.mcgill.ca/~birch/doc/forester/NHX.pdf
"""
root = Node("placeholder_root", E="1.1.1.1", D="N")
metazoa = Node(
"placeholder_metazoa",
length=0.1,
S="Metazoa",
E="1.1.1.1",
D="N",
parent=root,
)
primates = Node(
"placeholder_primates",
length=0.05,
S="Primates",
E="1.1.1.1",
D="Y",
B="100",
parent=metazoa,
def test_tree_to_newick_phylogenetic(phylogenetic_tree):
newick_str = tree_to_newick(
phylogenetic_tree,
intermediate_node_name=False,
length_attr="length",
attr_list=["S", "E", "D", "B"],
)
_ = Node("ADH2", length=0.1, S="human", E="1.1.1.1", parent=primates)
_ = Node("ADH1", length=0.11, S="human", E="1.1.1.1", parent=primates)
_ = Node("ADHY", length=0.1, S="nematode", E="1.1.1.1", parent=metazoa)
_ = Node("ADHX", length=0.12, S="insect", E="1.1.1.1", parent=metazoa)
fungi = Node("placeholder_fungi", length=0.1, S="Fungi", parent=root)
_ = Node("ADH4", length=0.09, S="yeast", E="1.1.1.1", parent=fungi)
_ = Node("ADH3", length=0.13, S="yeast", E="1.1.1.1", parent=fungi)
_ = Node("ADH2", length=0.12, S="yeast", E="1.1.1.1", parent=fungi)
_ = Node("ADH1", length=0.11, S="yeast", E="1.1.1.1", parent=fungi)
expected_str = "(((ADH2:0.1[&&NHX:S=human:E=1.1.1.1],ADH1:0.11[&&NHX:S=human:E=1.1.1.1]):0.05[&&NHX:S=Primates:E=1.1.1.1:D=Y:B=100],ADHY:0.1[&&NHX:S=nematode:E=1.1.1.1],ADHX:0.12[&&NHX:S=insect:E=1.1.1.1]):0.1[&&NHX:S=Metazoa:E=1.1.1.1:D=N],(ADH4:0.09[&&NHX:S=yeast:E=1.1.1.1],ADH3:0.13[&&NHX:S=yeast:E=1.1.1.1],ADH2:0.12[&&NHX:S=yeast:E=1.1.1.1],ADH1:0.11[&&NHX:S=yeast:E=1.1.1.1]):0.1[&&NHX:S=Fungi])[&&NHX:E=1.1.1.1:D=N]"
assert newick_str == expected_str

@staticmethod
def test_tree_to_newick_phylogenetic_attr_sep(phylogenetic_tree):
newick_str = tree_to_newick(
root,
phylogenetic_tree,
intermediate_node_name=False,
length_attr="length",
attr_list=["S", "E", "D", "B"],
attr_sep=";",
)
expected_str = """(((ADH2:0.1[&&NHX:S=human:E=1.1.1.1],ADH1:0.11[&&NHX:S=human:E=1.1.1.1]):0.05[&&NHX:S=Primates:E=1.1.1.1:D=Y:B=100],ADHY:0.1[&&NHX:S=nematode:E=1.1.1.1],ADHX:0.12[&&NHX:S=insect:E=1.1.1.1]):0.1[&&NHX:S=Metazoa:E=1.1.1.1:D=N],(ADH4:0.09[&&NHX:S=yeast:E=1.1.1.1],ADH3:0.13[&&NHX:S=yeast:E=1.1.1.1],ADH2:0.12[&&NHX:S=yeast:E=1.1.1.1],ADH1:0.11[&&NHX:S=yeast:E=1.1.1.1]):0.1[&&NHX:S=Fungi])[&&NHX:E=1.1.1.1:D=N]"""
expected_str = "(((ADH2:0.1[&&NHX:S=human;E=1.1.1.1],ADH1:0.11[&&NHX:S=human;E=1.1.1.1]):0.05[&&NHX:S=Primates;E=1.1.1.1;D=Y;B=100],ADHY:0.1[&&NHX:S=nematode;E=1.1.1.1],ADHX:0.12[&&NHX:S=insect;E=1.1.1.1]):0.1[&&NHX:S=Metazoa;E=1.1.1.1;D=N],(ADH4:0.09[&&NHX:S=yeast;E=1.1.1.1],ADH3:0.13[&&NHX:S=yeast;E=1.1.1.1],ADH2:0.12[&&NHX:S=yeast;E=1.1.1.1],ADH1:0.11[&&NHX:S=yeast;E=1.1.1.1]):0.1[&&NHX:S=Fungi])[&&NHX:E=1.1.1.1;D=N]"
assert newick_str == expected_str