read.beast() now reports a file that does not contain a tree instead of handing a text that is not Newick over to read.tree(), which parsed it into a meaningless tree and could crash the R session, e.g. the tabular output of MEGA (use read.mega_tabular() for it) (2026-09-20, Sun)
read.beast() is faster on a large file: the annotation of a node is parsed by a function that no longer calls use_perl() and %>% for every value and the tree it writes is not parsed a second time, a file of 500 trees took 33s and now takes 25s (2026-09-20, Sun)
read.phyloxml() is much faster and it is no longer limited to a tree nested less than 256 levels deep, the default limit of libxml2; the clade tree is now walked with an explicit stack instead of a recursion that bound all the nodes visited so far at every node, a tree of 512 tips took 7s and now takes 0.4s (2026-09-20, Sun)
edgeNum2nodeNum() is exported, it maps the edge_num of an EPA/pplacer placement (a post-order traversal number) to the node number of the reference tree, #31 (2026-09-20, Sun, #31)
read.beast() now supports the UTREE keyword of an unrooted tree and write.beast() no longer annotates a node without data (it wrote NULL and could stop with object 'nl' not found), which is what happened to the LSD2 timetree of IQ-TREE (2026-09-20, Sun, #111)
read.mcmctree() now stores the 95% credibility interval of the node age in a reltime_0.95_CI column (it used to be a column named 0.95) so that it can be plotted with geom_range(range='reltime_0.95_CI', center='reltime'), and the interval is kept as numbers (2026-09-20, Sun, #13)
the substitution is now reported with the node it cannot find a sequence for instead of failing with seqA should have equal length to seqB, and that message names the two sequences and their lengths (2026-09-20, Sun, #91)
read.iqtree() now says when the node labels hold a single support value that cannot be split into SH-aLRT and UFBoot (e.g. the standard bootstrap alone), and it no longer fails on a tree without any branch support (2026-09-20, Sun, #114)
read.iqtree() now reports that it cannot find a Newick tree in the input instead of parsing the IQ-TREE report file (*.iqtree) into a meaningless tree or crashing the R session (2026-09-20, Sun, #98)
as.phylo() now uses the branch.length column by default so that the branch lengths are not lost when a tree is re-rooted (2026-09-20, Sun, #134)
as.phylo() now uses the label column by default instead of the node numbers, so that the tip and node labels are not lost when a tree is re-rooted (2026-09-20, Sun, #120)
read.beast() and read.mega() now support a TRANSLATE table with non-consecutive keys (e.g. MEGA output); the tips are numbered 1:Ntip and the node data is mapped accordingly (2026-09-20, Sun, #132)
read.nextstrain.json() now parses trees with mixed attribute types (e.g. a divergence tree, where div is an integer), the numeric attributes were turned into characters when a node had a character attribute and bind_rows() refused to combine them (2026-09-20, Sun, #126)
read.raxml() supports a text= argument to parse a tree string or a connection (2026-09-20, Sun, #122)
read.raxml() now returns a treedataList for a file with several trees (e.g. RAxML_bootstrap.output) instead of failing (2026-09-20, Sun, #121)
the tree of a PAML output is now found when it is annotated (e.g. #1 for the branch models) and a file without a tree reports it instead of failing in strsplit(), #34 (2026-09-20, Sun, #34)
read.phyloxml() now keeps the branch lengths, as.phylo() was called with length= instead of branch.length= and the branch lengths were dropped (2026-09-20, Sun, #124)
read.paml_rst() now attributes the branch length to the node the branch leads to, they were taken by position and ended up on the wrong branch (2026-09-20, Sun, #72)
as.treedata() now takes the labels of a data.frame from its label column instead of from the node numbers, which produced label.x/label.y columns (2026-09-20, Sun, #87)
update offspring() to work as child(). Actually they are using the same function with different default (child(type = "children") and offspring(type="all")) (2022-03-16, Wed)
update child() to support different types (“children”, ‘tips’, ‘internal’, ‘external’, ‘all’) (2022-03-09, Wed, #75)
write.beast allows treedata object only contains phylo slot, then it will equivalent to write.nexus (2022-02-23, Wed)
treeio 1.19.1
bug fixed in groupClade.treedata to return a treedata object instead of phylo (2021-11-12, Fri)
treeio 1.18.0
Bioconductor 3.14 release
treeio 1.17.2
allow additional parameter to pass to drop.tip methods (2021-06-23, Wed, @xiangpin, #62)
as.phylo and as.treedata for data.frame (2021-06-12, Sat)
as.ultrametric method to force a tree to be ultrametric (2021-06-09, Wed)
introduce force.ultrametric parameter in read.mcmctree
treeio 1.17.1
read.mcmctree for PAML MCMCTree result (2021-06-04, Fri)
treeio 1.16.0
Bioconductor 3.13 release
treeio 1.15.6
optimized read.nhx for large tree file (2021-03-12, Fri)
Supports convert edge list (matrix, data.frame or tibble) to phylo and treedata object, now ggtree can be used to visualize all tree-like graph. (2018-04-23, Mon)