From 362183fa127df55286f820bb33814e1e72404599 Mon Sep 17 00:00:00 2001 From: Scott Claessens Date: Tue, 1 Oct 2024 18:22:49 +0100 Subject: [PATCH] #52 Require multiPhylo objects to have same number of branches --- R/coev_fit.R | 3 ++- R/coev_helpers.R | 10 ++++++++++ R/coev_make_stancode.R | 3 ++- R/coev_make_standata.R | 3 ++- man/coev_fit.Rd | 3 ++- man/coev_make_stancode.Rd | 3 ++- man/coev_make_standata.Rd | 3 ++- tests/testthat/test-coev_fit.R | 19 +++++++++++++++++++ tests/testthat/test-coev_make_stancode.R | 19 +++++++++++++++++++ tests/testthat/test-coev_make_standata.R | 19 +++++++++++++++++++ 10 files changed, 79 insertions(+), 6 deletions(-) diff --git a/R/coev_fit.R b/R/coev_fit.R index a973144..cd1bb71 100644 --- a/R/coev_fit.R +++ b/R/coev_fit.R @@ -27,7 +27,8 @@ #' the data. The id column must exactly match the tip labels in the phylogeny. #' @param tree A phylogenetic tree object of class \code{phylo} or #' \code{multiPhylo}. The tree(s) must be rooted and must include positive -#' non-zero branch lengths. +#' non-zero branch lengths. All trees in \code{multiPhylo} objects must have +#' the same number of internal nodes and branches. #' @param effects_mat (optional) A boolean matrix with row and column names #' exactly matching the variables declared for the model. If not specified, #' all cross-lagged effects will be estimated in the model. If specified, the diff --git a/R/coev_helpers.R b/R/coev_helpers.R index 8779122..2b90303 100644 --- a/R/coev_helpers.R +++ b/R/coev_helpers.R @@ -190,6 +190,16 @@ run_checks <- function(data, variables, id, tree, effects_mat, ) } } + # stop if trees have different numbers of internal nodes or branches + if (length(unique(lapply(tree, function(x) x$Nnode))) != 1 | + length(unique(lapply(tree, function(x) length(x$edge.length)))) != 1) { + stop2( + paste0( + "All trees in 'tree' argument must have the same number of ", + "internal nodes and branches." + ) + ) + } # stop if id in data contains missing values if (any(is.na(data[,id]))) { stop2("The id variable in the data must not contain NAs.") diff --git a/R/coev_make_stancode.R b/R/coev_make_stancode.R index 8535793..ebcfef5 100644 --- a/R/coev_make_stancode.R +++ b/R/coev_make_stancode.R @@ -19,7 +19,8 @@ #' the data. The id column must exactly match the tip labels in the phylogeny. #' @param tree A phylogenetic tree object of class \code{phylo} or #' \code{multiPhylo}. The tree(s) must be rooted and must include positive -#' non-zero branch lengths. +#' non-zero branch lengths. All trees in \code{multiPhylo} objects must have +#' the same number of internal nodes and branches. #' @param effects_mat (optional) A boolean matrix with row and column names #' exactly matching the variables declared for the model. If not specified, #' all cross-lagged effects will be estimated in the model. If specified, the diff --git a/R/coev_make_standata.R b/R/coev_make_standata.R index 479c5aa..8d16e88 100644 --- a/R/coev_make_standata.R +++ b/R/coev_make_standata.R @@ -20,7 +20,8 @@ #' the data. The id column must exactly match the tip labels in the phylogeny. #' @param tree A phylogenetic tree object of class \code{phylo} or #' \code{multiPhylo}. The tree(s) must be rooted and must include positive -#' non-zero branch lengths. +#' non-zero branch lengths. All trees in \code{multiPhylo} objects must have +#' the same number of internal nodes and branches. #' @param effects_mat (optional) A boolean matrix with row and column names #' exactly matching the variables declared for the model. If not specified, #' all cross-lagged effects will be estimated in the model. If specified, the diff --git a/man/coev_fit.Rd b/man/coev_fit.Rd index 59bafd6..3d7e883 100644 --- a/man/coev_fit.Rd +++ b/man/coev_fit.Rd @@ -37,7 +37,8 @@ the data. The id column must exactly match the tip labels in the phylogeny.} \item{tree}{A phylogenetic tree object of class \code{phylo} or \code{multiPhylo}. The tree(s) must be rooted and must include positive -non-zero branch lengths.} +non-zero branch lengths. All trees in \code{multiPhylo} objects must have +the same number of internal nodes and branches.} \item{effects_mat}{(optional) A boolean matrix with row and column names exactly matching the variables declared for the model. If not specified, diff --git a/man/coev_make_stancode.Rd b/man/coev_make_stancode.Rd index 7709765..e6e670a 100644 --- a/man/coev_make_stancode.Rd +++ b/man/coev_make_stancode.Rd @@ -36,7 +36,8 @@ the data. The id column must exactly match the tip labels in the phylogeny.} \item{tree}{A phylogenetic tree object of class \code{phylo} or \code{multiPhylo}. The tree(s) must be rooted and must include positive -non-zero branch lengths.} +non-zero branch lengths. All trees in \code{multiPhylo} objects must have +the same number of internal nodes and branches.} \item{effects_mat}{(optional) A boolean matrix with row and column names exactly matching the variables declared for the model. If not specified, diff --git a/man/coev_make_standata.Rd b/man/coev_make_standata.Rd index 3f89843..4dd55bd 100644 --- a/man/coev_make_standata.Rd +++ b/man/coev_make_standata.Rd @@ -36,7 +36,8 @@ the data. The id column must exactly match the tip labels in the phylogeny.} \item{tree}{A phylogenetic tree object of class \code{phylo} or \code{multiPhylo}. The tree(s) must be rooted and must include positive -non-zero branch lengths.} +non-zero branch lengths. All trees in \code{multiPhylo} objects must have +the same number of internal nodes and branches.} \item{effects_mat}{(optional) A boolean matrix with row and column names exactly matching the variables declared for the model. If not specified, diff --git a/tests/testthat/test-coev_fit.R b/tests/testthat/test-coev_fit.R index 672a3b1..55d6506 100644 --- a/tests/testthat/test-coev_fit.R +++ b/tests/testthat/test-coev_fit.R @@ -314,6 +314,25 @@ test_that("coev_fit() produces expected errors", { "The id variable in the data does not match tree tip labels exactly.", fixed = TRUE ) + expect_error( + { + tree2 <- c(tree, ape::di2multi(tree, tol = 0.01)) # collapse internal node + coev_fit( + data = d, + variables = list( + x = "bernoulli_logit", + y = "ordered_logistic" + ), + id = "id", + tree = tree2 + ) + }, + paste0( + "All trees in 'tree' argument must have the same number of ", + "internal nodes and branches." + ), + fixed = TRUE + ) expect_error( { d2 <- d; d2$id[1] <- NA diff --git a/tests/testthat/test-coev_make_stancode.R b/tests/testthat/test-coev_make_stancode.R index 3dad9e8..f3402dc 100644 --- a/tests/testthat/test-coev_make_stancode.R +++ b/tests/testthat/test-coev_make_stancode.R @@ -314,6 +314,25 @@ test_that("coev_make_stancode() produces expected errors", { "The id variable in the data does not match tree tip labels exactly.", fixed = TRUE ) + expect_error( + { + tree2 <- c(tree, ape::di2multi(tree, tol = 0.01)) # collapse internal node + coev_make_stancode( + data = d, + variables = list( + x = "bernoulli_logit", + y = "ordered_logistic" + ), + id = "id", + tree = tree2 + ) + }, + paste0( + "All trees in 'tree' argument must have the same number of ", + "internal nodes and branches." + ), + fixed = TRUE + ) expect_error( { d2 <- d; d2$id[1] <- NA diff --git a/tests/testthat/test-coev_make_standata.R b/tests/testthat/test-coev_make_standata.R index 46a0a08..168feaa 100644 --- a/tests/testthat/test-coev_make_standata.R +++ b/tests/testthat/test-coev_make_standata.R @@ -314,6 +314,25 @@ test_that("coev_make_standata() produces expected errors", { "The id variable in the data does not match tree tip labels exactly.", fixed = TRUE ) + expect_error( + { + tree2 <- c(tree, ape::di2multi(tree, tol = 0.01)) # collapse internal node + coev_make_standata( + data = d, + variables = list( + x = "bernoulli_logit", + y = "ordered_logistic" + ), + id = "id", + tree = tree2 + ) + }, + paste0( + "All trees in 'tree' argument must have the same number of ", + "internal nodes and branches." + ), + fixed = TRUE + ) expect_error( { d2 <- d; d2$id[1] <- NA