Skip to content

Commit a1b347a

Browse files
committed
prune inplace update() call fix
1 parent 052789b commit a1b347a

File tree

10 files changed

+898
-58
lines changed

10 files changed

+898
-58
lines changed

toytree/cli/cli_distance.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env python
2+
3+
4+
5+
# # toytree distance [options] TREE TREE ----------------------------------
6+
# parser_distance = subparsers.add_parser("distance", help="compute distance between trees")
7+
# parser_distance.add_argument("TREE1", type=str, help="tree1 newick file or string")
8+
# parser_distance.add_argument("TREE2", type=str, help="tree2 newick file or string")
9+
# parser_distance.add_argument(
10+
# "-m", type=str,
11+
# choices=['rf', 'rfi', 'rfj', 'qrt'],
12+
# default='rf',
13+
# help="distance metric method",
14+
# )
15+
# parser_distance.add_argument(
16+
# "-n", "--normalize", action="store_true",
17+
# help="normalize value between [0-1]")
18+
# return parser
19+
20+
21+
# # distance
22+
# if args.subcommand == "distance":
23+
# tree1 = toytree.tree(args.TREE1)
24+
# tree2 = toytree.tree(args.TREE2)
25+
# norm = {"normalize": args.normalize}
26+
# if args.m == "rf":
27+
# val = toytree.distance.get_treedist_rf(tree1, tree2, **norm)
28+
# elif args.m == "rfg_mci":
29+
# val = toytree.distance.get_treedist_rfg_mci(tree1, tree2, **norm)
30+
# elif args.m == "rfg_spi":
31+
# val = toytree.distance.get_treedist_rfg_spi(tree1, tree2, **norm)
32+
# elif args.m == "rfi":
33+
# val = toytree.distance.get_treedist_rfi(tree1, tree2, **norm)
34+
# elif args.m == "qrt":
35+
# val = toytree.distance.get_treedist_qrt(tree1, tree2)
36+
# sys.stdout.write(val)
37+
# return 0

toytree/cli/cli_draw.py

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,9 @@
44
import sys
55
import textwrap
66
import tempfile
7-
import os
8-
import platform
9-
import subprocess
10-
import shutil
11-
import webbrowser
127
from argparse import ArgumentParser, RawDescriptionHelpFormatter
138
from .make_wide import make_wide
14-
from loguru import logger
9+
# from loguru import logger
1510

1611

1712
KWARGS = dict(
@@ -32,9 +27,9 @@
3227
--------
3328
$ draw -i TRE.nwk -a
3429
$ draw -i TRE.nwk -f png -v
35-
$ draw -i TRE.nwk -f html -v -k ...
36-
$ draw -i TRE.nwk -f pdf -o /tmp/DRAWING
37-
$ draw -i TRE.nwk -v -N fill=red -E stroke=pink -T font-size=10px
30+
$ draw -i TRE.nwk -f html -v -ts c
31+
$ draw -i TRE.nwk -f pdf -o /tmp/DRAWING -ns 8 -nc teal -ta true
32+
$ draw -i TRE.nwk -v -N fill=red -E stroke=pink -T font-size=10px fill=blue
3833
$ root -i TRE.nwk -n R | draw -i - -v
3934
""")
4035
)
@@ -52,24 +47,31 @@ def get_parser_draw(parser: ArgumentParser | None = None) -> ArgumentParser:
5247
parser = ArgumentParser(**KWARGS)
5348

5449
# path args
55-
parser.add_argument("-i", "--input", type=Path, metavar="path", required=True, help="input tree file (nwk, nex or nhx)")
56-
parser.add_argument("-o", "--output", type=Path, metavar="path", help="optional basename of outfile path. If None prints to STDOUT")
50+
parser.add_argument("-i", "--input", type=Path, metavar="path", required=True, help="input tree file (nwk, nex or nhx) or stdin (-)")
51+
parser.add_argument("-o", "--output", type=Path, metavar="path", help="optional basename of output [/tmp/toytree].")
5752
# option
5853
parser.add_argument("-a", "--ascii", action="store_true", help="print ascii tree (overrides other draw args)")
59-
parser.add_argument("-f", "--format", choices=["html", "svg", "pdf", "png"], default="png", help="file format of drawing [png]")
60-
parser.add_argument("-v", "--view", type=str, metavar="app", const="auto", nargs="?", help="open drawing in default viewer, or provide an app name")
6154
parser.add_argument("-e", "--ladderize", action="store_true", help="ladderize the tree")
62-
parser.add_argument("-k", "--kwargs", type=str, metavar="str", nargs="*", help="any supported toytree.draw kwargs as 'key=val'")
55+
parser.add_argument("-f", "--format", choices=["html", "svg", "pdf", "png"], default="pdf", help="file format of drawing [pdf]")
56+
parser.add_argument("-v", "--view", type=str, metavar="app", const="auto", nargs="?", help="open drawing in default viewer, or provide an app name")
57+
# parser.add_argument("-k", "--kwargs", type=str, metavar="str", nargs="*", help="any supported toytree.draw kwargs as 'key=val'")
6358
parser.add_argument("-I", "--internal-labels", type=str, metavar="str", help="parse internal node feature (e.g., support) [auto]")
6459
parser.add_argument("-l", "--log-level", type=str, metavar="level", default="INFO", help="stderr logging level (DEBUG, [INFO], WARNING, ERROR)")
6560

66-
parser.add_argument("-ts", "--tree-style", type=str, metavar="str", help="base tree style [[None], 'r', 'c', 's', 'o', 'b']")
67-
parser.add_argument("-N", "--node-style", type=str, metavar="str", nargs="+", help="node style args")
68-
parser.add_argument("-E", "--edge-style", type=str, metavar="str", nargs="+", help="edge style args")
69-
parser.add_argument("-T", "--tip-labels-style", type=str, metavar="str", nargs="+", help="tip labels style args")
70-
parser.add_argument("-ns", "--node-sizes", type=int, metavar="int", nargs="+", default=[6], help="node sizes")
71-
parser.add_argument("-nc", "--node-colors", type=str, metavar="str", nargs="+", default=["#262626"], help="node colors")
72-
parser.add_argument("-tl", "--tip-labels-align", type=bool, metavar="bool", nargs="+", help="align tip labels")
61+
p = parser.add_argument_group(title="optional style args")
62+
p.add_argument("-wi", "--width", type=int, metavar="int", help="width in pixel units")
63+
p.add_argument("-he", "--height", type=int, metavar="int", help="height n pixel units")
64+
p.add_argument("-la", "--layout", type=str, metavar="str", help="layout [['r'], 'l', 'u', 'd', 'c', 'c0-180', 'un']")
65+
p.add_argument("-ts", "--tree-style", type=str, metavar="str", help="base tree style [['n'], 'r', 'c', 's', 'o', 'b']")
66+
p.add_argument("-ta", "--tip-labels-align", type=bool, metavar="bool", nargs="+", help="align tip labels")
67+
p.add_argument("-ns", "--node-sizes", type=int, metavar="int", nargs="+", default=[None], help="node sizes")
68+
p.add_argument("-nc", "--node-colors", type=str, metavar="str", nargs="+", default=[None], help="node colors")
69+
p.add_argument("-et", "--edge-type", type=str, metavar="str", choices=["p", "c", "b"], help="edge type ([phylogram], cladogram, bezier)")
70+
71+
p.add_argument("-N", "--node-style", type=str, metavar="str", nargs="+", help="node style args")
72+
p.add_argument("-E", "--edge-style", type=str, metavar="str", nargs="+", help="edge style args")
73+
p.add_argument("-T", "--tip-labels-style", type=str, metavar="str", nargs="+", help="tip labels style args")
74+
7375
# parser.add_argument("-L", "--log-file", type=Path, metavar="path", help="append stderr log to a file")
7476
return parser
7577

@@ -79,6 +81,12 @@ def open_with_default_viewer(path: str) -> bool:
7981
"""Try to open a file with the system's default app.
8082
Returns True on (likely) success, False if we had no good option.
8183
"""
84+
import os
85+
import platform
86+
import subprocess
87+
import shutil
88+
import webbrowser
89+
8290
path = os.path.abspath(path)
8391
system = platform.system()
8492

@@ -111,7 +119,7 @@ def open_with_default_viewer(path: str) -> bool:
111119

112120
except Exception:
113121
# You might want to log this if you have logging set up
114-
logger.bind(name="toytree").error("could not find a default viewer to open drawing file")
122+
raise OSError("could not find a default viewer to open drawing file")
115123
return False
116124

117125

@@ -132,7 +140,7 @@ def run_draw(args):
132140

133141
# ascii tree drawing
134142
if args.ascii:
135-
print(tre.treenode.draw_ascii(), sys.stdout)
143+
tre.treenode.draw_ascii()
136144
return 0
137145

138146
# create drawing
@@ -142,12 +150,17 @@ def run_draw(args):
142150
# else:
143151
# kwargs = {}
144152
canvas, axes, mark = tre.draw(
153+
height=args.height,
154+
width=args.width,
145155
tree_style=args.tree_style,
156+
layout=args.layout,
157+
tip_labels_align=args.tip_labels_align,
158+
node_sizes=args.node_sizes if len(args.node_sizes) > 1 else args.node_sizes[0],
159+
node_colors=args.node_colors if len(args.node_colors) > 1 else args.node_colors[0],
146160
node_style=dict(tuple(i.split("=") for i in args.node_style)) if args.node_style else {},
147161
edge_style=dict(tuple(i.split("=") for i in args.edge_style)) if args.edge_style else {},
148162
tip_labels_style=dict(tuple(i.split("=") for i in args.tip_labels_style)) if args.tip_labels_style else {},
149-
node_sizes=args.node_sizes if len(args.node_sizes) > 1 else args.node_sizes[0],
150-
# node_colors=args.node_colors if len(args.node_colors) > 1 else args.node_colors[0],
163+
edge_type=args.edge_type,
151164
# tip_labels_align=args.tip_labels_align,
152165
# **kwargs
153166
)
@@ -161,7 +174,7 @@ def run_draw(args):
161174
prefix = prefix / "toytree"
162175
out = Path(f"{prefix}").with_suffix(suffix)
163176
else:
164-
out = tempfile.NamedTemporaryFile(prefix="toytree", suffix=suffix, delete=False)
177+
out = tempfile.NamedTemporaryFile(prefix="toytree-", suffix=suffix, delete=False)
165178
out = out.name
166179
save(canvas, out)
167180

@@ -182,4 +195,5 @@ def main():
182195
# except ToytreeError as exc:
183196
# logger.bind(name="toytree").error(exc)
184197
except Exception as exc:
185-
logger.bind(name="toytree").exception(exc)
198+
raise exc
199+
# logger.bind(name="toytree").exception(exc)

toytree/cli/cli_get_node_data.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import textwrap
99
from pathlib import Path
1010
from argparse import ArgumentParser, RawDescriptionHelpFormatter
11-
from loguru import logger
11+
# from loguru import logger
1212
from .make_wide import make_wide
1313
# from ortholab.utils.parallel import run_pipeline # , run_with_pool
1414
# from ortholab.utils.logger_setup import set_log_level
@@ -81,8 +81,7 @@ def run_get_node_data(args):
8181
data = sys.stdin.read()
8282
tre = tree(data, internal_labels=args.internal_labels)
8383
else:
84-
data = args.input.expanduser().absolute()
85-
tre = tree(data, internal_labels=args.internal_labels)
84+
tre = tree(args.input, internal_labels=args.internal_labels)
8685

8786
# get data
8887
if args.tips_only:
@@ -116,5 +115,6 @@ def main():
116115
try:
117116
main()
118117
except Exception as exc:
119-
logger.bind(name="toytree").error(exc)
118+
raise exc
119+
# logger.bind(name="toytree").error(exc)
120120

toytree/cli/cli_prune.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import textwrap
99
from pathlib import Path
1010
from argparse import ArgumentParser, RawDescriptionHelpFormatter
11-
from loguru import logger
11+
# from loguru import logger
1212
from .make_wide import make_wide
1313

1414

@@ -46,6 +46,14 @@
4646
)
4747

4848

49+
50+
def string_or_stdin_parse(intree: str) -> str:
51+
"""If TREE is stdin then return the string from stdin."""
52+
if intree == "-":
53+
return sys.stdin.read().strip()
54+
return intree
55+
56+
4957
def get_parser_prune(parser: ArgumentParser | None = None) -> ArgumentParser:
5058
"""Return a parser tool for this method.
5159
"""
@@ -58,13 +66,14 @@ def get_parser_prune(parser: ArgumentParser | None = None) -> ArgumentParser:
5866
parser = ArgumentParser(**KWARGS)
5967

6068
# path args
61-
parser.add_argument("-i", "--input", type=Path, metavar="path", required=True, help="input CDS sequence (aligned or unaligned)")
69+
parser.add_argument("-i", "--input", type=string_or_stdin_parse, metavar="path", required=True, help="input CDS sequence (aligned or unaligned)")
6270
parser.add_argument("-o", "--output", type=Path, metavar="path", help="optional outfile path name. If None prints to STDOUT")
6371
parser.add_argument("-n", "--nodes", type=str, metavar="str", nargs="*", help="One or more names or regular expressions to select nodes")
6472
# options
6573
parser.add_argument("-r", "--require-root", action="store_true", help="keep root node even if unary after pruning children")
6674
parser.add_argument("-p", "--not-preserve-dists", action="store_true", help="if not preserved then children do not inherit parent dists")
6775
parser.add_argument("-I", "--internal-labels", type=str, metavar="str", help="parse internal node feature (e.g., support) [auto]")
76+
parser.add_argument("-x", "--exclude-features", action="store_true", help="do not preserve node feature data")
6877
# parser.add_argument("-f", "--force", action="store_true", help="overwrite existing result files in outdir")
6978
# parser.add_argument("-l", "--log-level", type=str, metavar="level", default="INFO", help="stderr logging level (DEBUG, [INFO], WARNING, ERROR)")
7079
# parser.add_argument("-L", "--log-file", type=Path, metavar="path", help="append stderr log to a file")
@@ -80,15 +89,20 @@ def run_prune(args):
8089
data = sys.stdin.read()
8190
tre = tree(data, internal_labels=args.internal_labels)
8291
else:
83-
data = args.input.expanduser().absolute()
84-
tre = tree(data, internal_labels=args.internal_labels)
92+
tre = tree(args.input, internal_labels=args.internal_labels)
8593

8694
# operate
8795
tre = prune(tre, *args.nodes, preserve_dists=(not args.not_preserve_dists), require_root=args.require_root)
96+
97+
# write tree with or wi/o feature data
98+
if args.exclude_features:
99+
features = None
100+
else:
101+
features = set(tre.features) - {'name', 'height', 'dist', 'support'}
88102
if args.output:
89-
tre.write(args.output)
103+
tre.write(args.output, features=features)
90104
else:
91-
sys.stdout.write(tre.write(None) + "\n")
105+
sys.stdout.write(tre.write(None, features=features) + "\n")
92106

93107

94108
def main():
@@ -102,4 +116,4 @@ def main():
102116
try:
103117
main()
104118
except Exception as exc:
105-
logger.bind(name="toytree").error(exc)
119+
raise exc

toytree/cli/cli_root.py

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import textwrap
99
from argparse import ArgumentParser, RawDescriptionHelpFormatter
1010
from .make_wide import make_wide
11-
from loguru import logger
11+
# from loguru import logger
12+
# logger = logger.bind(name="toytree")
1213

1314

1415
KWARGS = dict(
@@ -27,13 +28,21 @@
2728
Examples
2829
--------
2930
$ root -i TRE.nwk -n R > RTRE.nwk
30-
$ root -i TRE.nwk -n '~prefix' -o RTRE.nwk
31+
$ root -i TRE.nwk -n ~prefix -o RTRE.nwk
3132
$ root -i TRE.nwk -n A B C --mad > RTRE.nwk
3233
$ root -i TRE.nwk --mad > RTRE.nwk
34+
$ root -i TRE.nwk --mad -n ~[A-C] -x -I support > RTRE.nwk
3335
""")
3436
)
3537

3638

39+
def string_or_stdin_parse(intree: str) -> str:
40+
"""If TREE is stdin then return the string from stdin."""
41+
if intree == "-":
42+
return sys.stdin.read().strip()
43+
return intree
44+
45+
3746
def get_parser_root(parser: ArgumentParser | None = None) -> ArgumentParser:
3847
"""Return a parser tool for this method.
3948
"""
@@ -46,15 +55,16 @@ def get_parser_root(parser: ArgumentParser | None = None) -> ArgumentParser:
4655
parser = ArgumentParser(**KWARGS)
4756

4857
# path args
49-
parser.add_argument("-i", "--input", type=Path, metavar="path", required=True, help="input tree file (nwk, nex or nhx)")
58+
parser.add_argument("-i", "--input", type=string_or_stdin_parse, metavar="path", required=True, help="input tree file (nwk, nex or nhx)")
5059
parser.add_argument("-o", "--output", type=Path, metavar="path", help="optional outfile path name. If None prints to STDOUT")
5160
parser.add_argument("-n", "--nodes", type=str, metavar="str", nargs="*", help="one or more names or regular expressions to select outgroup mrca")
5261
# options
5362
parser.add_argument("-I", "--internal-labels", type=str, metavar="str", help="parse internal node feature (e.g., support) [auto]")
54-
parser.add_argument("-m", "--mad", action="store_true", help="use minimal-ancestor-deviation rooting")
5563
parser.add_argument("-e", "--edge-features", type=str, metavar="str", nargs="*", help="one or more edge features on tree that should be re-polarized")
64+
parser.add_argument("-x", "--exclude-features", action="store_true", help="do not preserve node feature data")
65+
parser.add_argument("-m", "--mad", action="store_true", help="use minimal-ancestor-deviation to find rooting or place node on selected edge")
5666
parser.add_argument("-s", "--stats", action="store_true", help="return tree and mad stats")
57-
parser.add_argument("-d", "--min-dist", type=float, default=1e-12, help="zero-length edges set to min_dist [1e-12] during mad to prevent division.")
67+
parser.add_argument("-d", "--min-dist", type=float, metavar="float", default=1e-12, help="set zero-length edges to [1e-12] during mad to prevent division error")
5868
parser.add_argument("-l", "--log-level", type=str, metavar="level", default="INFO", help="stderr logging level (DEBUG, [INFO], WARNING, ERROR)")
5969
# parser.add_argument("-L", "--log-file", type=Path, metavar="path", help="append stderr log to a file")
6070
return parser
@@ -72,20 +82,27 @@ def run_root(args):
7282
data = sys.stdin.read()
7383
tre = tree(data, internal_labels=args.internal_labels)
7484
else:
75-
data = args.input.expanduser().absolute()
76-
tre = tree(data, internal_labels=args.internal_labels)
85+
tre = tree(args.input, internal_labels=args.internal_labels)
7786

7887
# root
7988
args.nodes = [] if not args.nodes else args.nodes
8089
if args.mad:
81-
root_on_minimal_ancestor_deviation(tre, *args.nodes, inplace=True, return_stats=args.stats, min_dist=args.min_dist, edge_features=args.edge_features)
90+
_, mdict = root_on_minimal_ancestor_deviation(tre, *args.nodes, inplace=True, return_stats=True, min_dist=args.min_dist, edge_features=args.edge_features)
91+
if args.stats:
92+
for key in mdict:
93+
print(f"{key}={mdict[key]}")
8294
else:
8395
root(tre, *args.nodes, inplace=True, edge_features=args.edge_features)
96+
97+
# write tree with or wi/o feature data
98+
if args.exclude_features:
99+
features = None
100+
else:
101+
features = set(tre.features) - {'name', 'height', 'dist', 'support'}
84102
if args.output:
85-
tre.write(args.output)
103+
tre.write(args.output, features=features)
86104
else:
87-
sys.stdout.write(tre.write(None) + "\n")
88-
105+
sys.stdout.write(tre.write(None, features=features) + "\n")
89106

90107

91108
def main():
@@ -100,4 +117,5 @@ def main():
100117
# except ToytreeError as exc:
101118
# logger.bind(name="toytree").error(exc)
102119
except Exception as exc:
103-
logger.bind(name="toytree").error(exc)
120+
raise exc
121+
# logger.error(exc)

0 commit comments

Comments
 (0)