Skip to content

Commit 403dfe7

Browse files
authored
Merge pull request #159 from kayjan/hyield-add-arg
Hyield add arg
2 parents 8964292 + 330c408 commit 403dfe7

File tree

4 files changed

+61
-7
lines changed

4 files changed

+61
-7
lines changed

bigtree/tree/construct.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,10 +1182,14 @@ def _raise_value_error(tree_idx: int) -> None:
11821182
NewickState.PARSE_STRING,
11831183
NewickState.PARSE_ATTRIBUTE_NAME,
11841184
]:
1185+
if cumulative_string:
1186+
_raise_value_error(tree_string_idx)
11851187
cumulative_string = tree_string[
11861188
tree_string_idx + 1 : quote_end_idx # noqa: E203
11871189
]
11881190
else:
1191+
if cumulative_string_value:
1192+
_raise_value_error(tree_string_idx)
11891193
cumulative_string_value = tree_string[
11901194
tree_string_idx + 1 : quote_end_idx # noqa: E203
11911195
]

bigtree/tree/export.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ def hprint_tree(
377377
tree: T,
378378
node_name_or_path: str = "",
379379
max_depth: int = 0,
380+
intermediate_node_name: bool = True,
380381
style: str = "const",
381382
custom_style: Iterable[str] = [],
382383
) -> None:
@@ -457,12 +458,14 @@ def hprint_tree(
457458
tree (Node): tree to print
458459
node_name_or_path (str): node to print from, becomes the root node of printing
459460
max_depth (int): maximum depth of tree to print, based on `depth` attribute, optional
461+
intermediate_node_name (bool): indicator if intermediate nodes have node names, defaults to True
460462
style (str): style of print, defaults to const style
461463
custom_style (Iterable[str]): style of icons, used when `style` is set to 'custom'
462464
"""
463465
result = hyield_tree(
464466
tree,
465467
node_name_or_path=node_name_or_path,
468+
intermediate_node_name=intermediate_node_name,
466469
max_depth=max_depth,
467470
style=style,
468471
custom_style=custom_style,
@@ -474,6 +477,7 @@ def hyield_tree(
474477
tree: T,
475478
node_name_or_path: str = "",
476479
max_depth: int = 0,
480+
intermediate_node_name: bool = True,
477481
style: str = "const",
478482
custom_style: Iterable[str] = [],
479483
) -> List[str]:
@@ -555,6 +559,7 @@ def hyield_tree(
555559
tree (Node): tree to print
556560
node_name_or_path (str): node to print from, becomes the root node of printing
557561
max_depth (int): maximum depth of tree to print, based on `depth` attribute, optional
562+
intermediate_node_name (bool): indicator if intermediate nodes have node names, defaults to True
558563
style (str): style of print, defaults to const style
559564
custom_style (Iterable[str]): style of icons, used when `style` is set to 'custom'
560565
@@ -609,9 +614,10 @@ def hyield_tree(
609614

610615
# Calculate padding
611616
space = " "
612-
padding_depths = {}
613-
for _idx, _children in enumerate(levelordergroup_iter(tree)):
614-
padding_depths[_idx + 1] = max([len(node.node_name) for node in _children])
617+
padding_depths = collections.defaultdict(int)
618+
if intermediate_node_name:
619+
for _idx, _children in enumerate(levelordergroup_iter(tree)):
620+
padding_depths[_idx + 1] = max([len(node.node_name) for node in _children])
615621

616622
def _hprint_branch(_node: T) -> Tuple[List[str], int]:
617623
"""Get string for tree horizontally.
@@ -623,17 +629,19 @@ def _hprint_branch(_node: T) -> Tuple[List[str], int]:
623629
Returns:
624630
(Tuple[List[str], int]): Intermediate/final result for node, index of branch
625631
"""
626-
padding_depth = padding_depths[_node.depth]
627-
padding = space * (padding_depth + 4)
628-
node_name_centered = _node.node_name.center(padding_depth)
632+
node_name_centered = _node.node_name.center(padding_depths[_node.depth])
629633

630634
children = list(_node.children)
631635
if not len(children):
632636
node_str = f"{style_branch} {node_name_centered.rstrip()}"
633637
return [node_str], 0
634638

635639
result, result_nrow, result_idx = [], [], []
636-
node_str = f"""{style_branch} {node_name_centered} {style_branch}"""
640+
if intermediate_node_name:
641+
node_str = f"""{style_branch} {node_name_centered} {style_branch}"""
642+
else:
643+
node_str = f"""{style_branch}{style_branch}{style_branch}"""
644+
padding = space * len(node_str)
637645
for idx, child in enumerate(children):
638646
result_child, result_branch_idx = _hprint_branch(child)
639647
result.extend(result_child)

tests/tree/test_construct.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,6 +2554,24 @@ def test_newick_to_tree_node_type(self):
25542554
)
25552555
assert_tree_structure_node_root(root)
25562556

2557+
def test_newick_to_tree_invalid_character_error(self):
2558+
newick_strs_error = [
2559+
(
2560+
"""((d,(g,h)e)b,(f)c)"'a'\"""",
2561+
19,
2562+
), # NewickCharacter.ATTR_QUOTE, wrong order of bracket (name)
2563+
(
2564+
"""((d,(g,h)e)b,(f[age="'38'"])c)a""",
2565+
21,
2566+
), # NewickCharacter.ATTR_QUOTE, wrong order of bracket (attr value)
2567+
]
2568+
for newick_str, error_idx in newick_strs_error:
2569+
with pytest.raises(ValueError) as exc_info:
2570+
newick_to_tree(newick_str)
2571+
assert str(exc_info.value) == Constants.ERROR_NODE_NEWICK_NOT_CLOSED.format(
2572+
index=error_idx
2573+
)
2574+
25572575

25582576
def assert_tree_structure_phylogenetic(root):
25592577
assert root.max_depth == 4, f"Expected max_depth 4, received {root.max_depth}"

tests/tree/test_export.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,30 @@ def test_hprint_tree_child_node_path(tree_node):
316316
node_name_or_path="a/b",
317317
)
318318

319+
@staticmethod
320+
def test_hprint_tree_intermediate_node_name(tree_node):
321+
expected_str = (
322+
" ┌─ d\n ┌───┤ ┌─ g\n───┤ └───┤\n │ └─ h\n └───── f\n"
323+
)
324+
assert_print_statement(
325+
hprint_tree,
326+
expected_str,
327+
tree=tree_node,
328+
intermediate_node_name=False,
329+
)
330+
331+
@staticmethod
332+
def test_hprint_tree_intermediate_node_name_diff_node_name_length(tree_node):
333+
tree_node["b"].name = "bcde"
334+
tree_node["c"]["f"].name = "fghijk"
335+
expected_str = " ┌─ d\n ┌───┤ ┌─ g\n───┤ └───┤\n │ └─ h\n └───── fghijk\n"
336+
assert_print_statement(
337+
hprint_tree,
338+
expected_str,
339+
tree=tree_node,
340+
intermediate_node_name=False,
341+
)
342+
319343
@staticmethod
320344
def test_hprint_tree_style_ansi(tree_node):
321345
expected_str = " /- d\n /- b -+ /- g\n- a -+ \\- e -+\n | \\- h\n \\- c --- f\n"

0 commit comments

Comments
 (0)