Skip to content

Commit

Permalink
Small trees in root_on_node
Browse files Browse the repository at this point in the history
  • Loading branch information
ms609 committed Jun 28, 2024
1 parent f9c7241 commit 90d3f00
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 6 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: TreeTools
Title: Create, Modify and Analyse Phylogenetic Trees
Version: 1.11.1.9001
Version: 1.11.1.9002
Authors@R: c(
person("Martin R.", 'Smith', role = c("aut", "cre", "cph"),
email = "martin.smith@durham.ac.uk",
Expand Down
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# TreeTools 1.11.1.9002 (2024-06-28) #

- `root_on_node()` handles trees with < 2 leaves.


# TreeTools 1.11.1.9001 (2024-06-19) #

- `J1Index()` computes the robust, universal tree balance measure of
Expand Down
14 changes: 9 additions & 5 deletions inst/include/TreeTools/root_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,27 @@ namespace TreeTools {
const Rcpp::IntegerVector child,
const Rcpp::DoubleVector weight);

// #TODO Write test cases
// edge must be BINARY
// edge must be in preorder
//
// Benchmarking at 2024-02-23 established that this is consistently twice
// as fast as root_on_node, so is worth retaining,
// despite some overlap in code.
//
// #TODO Write test cases
//
// [[Rcpp::export]]
inline Rcpp::IntegerMatrix root_binary(const Rcpp::IntegerMatrix edge,
const int outgroup) {

if (edge(0, 1) == outgroup) return edge;

const intx n_edge = edge.nrow(),
n_node = n_edge / 2,
n_tip = n_node + 1,
root_node = n_tip + 1,
max_node = n_node + n_tip;


if (!n_edge || !n_node || n_tip < 2) return edge;
if (edge(0, 1) == outgroup) return edge;
if (outgroup < 1) {
Rcpp::stop("`outgroup` must be a positive integer");
}
Expand Down Expand Up @@ -102,8 +105,9 @@ namespace TreeTools {
n_tip = max_node - n_node,
root_node = n_tip + 1
;
const bool weighted = phy.containsElementNamed("edge.length");
if (!n_edge || !n_node || n_tip < 2) return phy;

const bool weighted = phy.containsElementNamed("edge.length");
if (weighted) {
Rcpp::List reweighted = preorder_weighted(
edge(Rcpp::_, 0),
Expand Down
13 changes: 13 additions & 0 deletions tests/testthat/test-root_tree.h.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ test_that("Big trees don't fail", {
PectinateTree(2^14 + 1))
})

test_that("Small trees are rootable", {
ztt <- ZeroTaxonTree()
expect_equal(root_on_node(ztt, 1), ztt)
expect_equal(root_binary(ztt[["edge"]], 1), ztt$edge)
expect_equal(root_on_node(ztt, 999), ztt)

stt <- SingleTaxonTree()
expect_equal(root_on_node(stt, 1), stt)
expect_equal(root_on_node(stt, 2), root_on_node(stt, 1))
})

test_that("Binary trees are rootable", {
Test <- function(tree, root) {
expect_equal(Preorder(ApeRoot(tree, tree$tip.label[root]))$edge,
Expand All @@ -33,6 +44,7 @@ test_that("Binary trees are rootable", {
ed9 <- PectinateTree(9)$edge
expect_equal(root_binary(ed9, 10), ed9)
expect_equal(root_binary(ed9, 1), ed9)
expect_error(root_binary(ed9, 9999), "exceeds number of nodes")
})

test_that("Polytomous trees are rootable", {
Expand Down Expand Up @@ -78,6 +90,7 @@ test_that("Rooted trees report preorder accurately", {

expect_preorder(root_binary(edge, 2))
expect_preorder(root_binary(edge, 6))
expect_error(root_binary(edge, 999), "exceeds number of nodes")

tree <- structure(list(edge = edge,
Nnode = nTips - 1L,
Expand Down

0 comments on commit 90d3f00

Please sign in to comment.