diff --git a/DESCRIPTION b/DESCRIPTION index 7a7bc02b..17d7b9b9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: Quartet -Version: 1.2.7 +Version: 1.3.0 Title: Comparison of Phylogenetic Trees Using Quartet and Split Measures Description: Calculates the number of four-taxon subtrees consistent with a pair of cladograms, calculating the symmetric quartet distance of Bandelt & Dress @@ -46,6 +46,7 @@ Suggests: Rcpp, rmarkdown, testthat, + TreeDist, usethis, vdiffr, Config/Needs/check: diff --git a/NAMESPACE b/NAMESPACE index 5fba584e..5df0b9c1 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -36,6 +36,7 @@ export(PairSharedQuartetStatus) export(PairSharedSplitStatus) export(PairsQuartetDistance) export(PairsTripletDistance) +export(PairwiseQuartets) export(PlotQuartet) export(QuartetAgreement) export(QuartetDistance) diff --git a/NEWS.md b/NEWS.md index 44dfc7c7..d95281eb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# Quartet v1.3.0 (2025-01-16) + +- `PairwiseQuartets()` compares quartet statuses between all pairs of trees. + # Quartet v1.2.7 (2024-10-31) - `VizualizeQuartet()` now returns calculation results. diff --git a/Quartet.Rproj b/Quartet.Rproj index 8835ddff..faefa353 100644 --- a/Quartet.Rproj +++ b/Quartet.Rproj @@ -1,4 +1,5 @@ Version: 1.0 +ProjectId: 69de0ca2-bd58-49e4-8173-98d3d2d703f4 RestoreWorkspace: Yes SaveWorkspace: No diff --git a/R/PairwiseQuartets.R b/R/PairwiseQuartets.R new file mode 100644 index 00000000..310b56f5 --- /dev/null +++ b/R/PairwiseQuartets.R @@ -0,0 +1,40 @@ +#' Pairwise quartet distances +#' +#' Computes the quartet distance between each pair of trees in a list. +#' +#' @inheritParams QuartetStatus +#' @param Measure a function that calculates tree similarity or difference +#' from quartet statuses. Default is [`QuartetDivergence()`]. +#' @return a matrix specifying the distance between each tree and +#' each other tree in the `trees`. +#' +#' @template MRS +#' +#' @examples +#' data("sq_trees") +#' # Calculate the status of each quartet relative to the first entry in +#' # sq_trees +#' sq_status <- QuartetStatus(sq_trees) +#' +#' # Calculate Estabrook et al's similarity measures: +#' SimilarityMetrics(sq_status) +#' +#' # Compare trees that include a subset of the taxa 1..10 +#' library("TreeTools", quietly = TRUE, warn.conflict = FALSE) +#' QuartetStatus(BalancedTree(1:5), BalancedTree(3:8), nTip = 10) +#' +#' # If all taxa studied occur in `trees` or `cf`, set `nTip = TRUE` +#' QuartetStatus(BalancedTree(1:5), BalancedTree(3:10), nTip = TRUE) +#' +#' @family element-by-element comparisons +#' @seealso +#' - Use splits (groups/clades defined by nodes or edges of the tree) instead +#' of quartets as the unit of comparison: [`SplitStatus()`]. +#' +#' - Generate distance metrics from quartet statuses: [`SimilarityMetrics()`]. +#' +#' @references \insertAllCited{} +#' @export +PairwiseQuartets <- function(trees, Measure = QuartetDivergence) { + Measure(ManyToManyQuartetAgreement(trees)) +} diff --git a/R/tqDist.r b/R/tqDist.r index 1bb02c7c..d3a99626 100644 --- a/R/tqDist.r +++ b/R/tqDist.r @@ -60,7 +60,8 @@ #' - Use splits (groups/clades defined by nodes or edges of the tree) instead #' of quartets as the unit of comparison: [`SplitStatus()`]. #' -#' - Generate distance metrics from quartet statuses: [`SimilarityMetrics()`]. +#' - Generate distance metrics from quartet statuses: [`SimilarityMetrics()`], +#' `[PairwiseQuartets()]`. #' #' @references \insertAllCited{} #' @@ -249,8 +250,8 @@ ManyToManyQuartetAgreement <- function (trees, nTip = NULL) { } } -#' @describeIn QuartetStatus Agreement of each quartet in trees in one list with -#' each quartet in trees in a second list. +#' @describeIn QuartetStatus Agreement of each quartet in trees in `trees1` with +#' each quartet in trees in `trees2`. #' @param trees1,trees2 List or `multiPhylo` objects containing #' trees of class `phylo`. #' @return `TwoListQuartetAgreement()` returns a three-dimensional array listing, diff --git a/man/CompareQuartets.Rd b/man/CompareQuartets.Rd index cf1b86ce..3d7b5ef1 100644 --- a/man/CompareQuartets.Rd +++ b/man/CompareQuartets.Rd @@ -48,6 +48,7 @@ Other element-by-element comparisons: \code{\link{CompareQuartetsMulti}()}, \code{\link{CompareSplits}()}, \code{\link{PairSharedQuartetStatus}()}, +\code{\link{PairwiseQuartets}()}, \code{\link{QuartetState}()}, \code{\link{SharedQuartetStatus}()}, \code{\link{SplitStatus}()} diff --git a/man/CompareQuartetsMulti.Rd b/man/CompareQuartetsMulti.Rd index 64d218a6..93717a9f 100644 --- a/man/CompareQuartetsMulti.Rd +++ b/man/CompareQuartetsMulti.Rd @@ -68,6 +68,7 @@ Other element-by-element comparisons: \code{\link{CompareQuartets}()}, \code{\link{CompareSplits}()}, \code{\link{PairSharedQuartetStatus}()}, +\code{\link{PairwiseQuartets}()}, \code{\link{QuartetState}()}, \code{\link{SharedQuartetStatus}()}, \code{\link{SplitStatus}()} diff --git a/man/CompareSplits.Rd b/man/CompareSplits.Rd index 479a17fb..7ce24eeb 100644 --- a/man/CompareSplits.Rd +++ b/man/CompareSplits.Rd @@ -57,6 +57,7 @@ Other element-by-element comparisons: \code{\link{CompareQuartets}()}, \code{\link{CompareQuartetsMulti}()}, \code{\link{PairSharedQuartetStatus}()}, +\code{\link{PairwiseQuartets}()}, \code{\link{QuartetState}()}, \code{\link{SharedQuartetStatus}()}, \code{\link{SplitStatus}()} diff --git a/man/PairSharedQuartetStatus.Rd b/man/PairSharedQuartetStatus.Rd index 502164ac..1bf43471 100644 --- a/man/PairSharedQuartetStatus.Rd +++ b/man/PairSharedQuartetStatus.Rd @@ -32,6 +32,7 @@ Other element-by-element comparisons: \code{\link{CompareQuartets}()}, \code{\link{CompareQuartetsMulti}()}, \code{\link{CompareSplits}()}, +\code{\link{PairwiseQuartets}()}, \code{\link{QuartetState}()}, \code{\link{SharedQuartetStatus}()}, \code{\link{SplitStatus}()} diff --git a/man/PairwiseQuartets.Rd b/man/PairwiseQuartets.Rd new file mode 100644 index 00000000..9baf5463 --- /dev/null +++ b/man/PairwiseQuartets.Rd @@ -0,0 +1,63 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PairwiseQuartets.R +\name{PairwiseQuartets} +\alias{PairwiseQuartets} +\title{Pairwise quartet distances} +\usage{ +PairwiseQuartets(trees, Measure = QuartetDivergence) +} +\arguments{ +\item{trees}{A list of trees of class \code{\link[ape:read.tree]{phylo}}, +with identically labelled tips.} + +\item{Measure}{a function that calculates tree similarity or difference +from quartet statuses. Default is \code{\link[=QuartetDivergence]{QuartetDivergence()}}.} +} +\value{ +a matrix specifying the distance between each tree and +each other tree in the \code{trees}. +} +\description{ +Computes the quartet distance between each pair of trees in a list. +} +\examples{ +data("sq_trees") +# Calculate the status of each quartet relative to the first entry in +# sq_trees +sq_status <- QuartetStatus(sq_trees) + +# Calculate Estabrook et al's similarity measures: +SimilarityMetrics(sq_status) + +# Compare trees that include a subset of the taxa 1..10 +library("TreeTools", quietly = TRUE, warn.conflict = FALSE) +QuartetStatus(BalancedTree(1:5), BalancedTree(3:8), nTip = 10) + +# If all taxa studied occur in `trees` or `cf`, set `nTip = TRUE` +QuartetStatus(BalancedTree(1:5), BalancedTree(3:10), nTip = TRUE) + +} +\references{ +\insertAllCited{} +} +\seealso{ +\itemize{ +\item Use splits (groups/clades defined by nodes or edges of the tree) instead +of quartets as the unit of comparison: \code{\link[=SplitStatus]{SplitStatus()}}. +\item Generate distance metrics from quartet statuses: \code{\link[=SimilarityMetrics]{SimilarityMetrics()}}. +} + +Other element-by-element comparisons: +\code{\link{CompareQuartets}()}, +\code{\link{CompareQuartetsMulti}()}, +\code{\link{CompareSplits}()}, +\code{\link{PairSharedQuartetStatus}()}, +\code{\link{QuartetState}()}, +\code{\link{SharedQuartetStatus}()}, +\code{\link{SplitStatus}()} +} +\author{ +\href{https://orcid.org/0000-0001-5660-1727}{Martin R. Smith} +(\href{mailto:martin.smith@durham.ac.uk}{martin.smith@durham.ac.uk}) +} +\concept{element-by-element comparisons} diff --git a/man/QuartetState.Rd b/man/QuartetState.Rd index dd48ca49..51135083 100644 --- a/man/QuartetState.Rd +++ b/man/QuartetState.Rd @@ -84,6 +84,7 @@ Other element-by-element comparisons: \code{\link{CompareQuartetsMulti}()}, \code{\link{CompareSplits}()}, \code{\link{PairSharedQuartetStatus}()}, +\code{\link{PairwiseQuartets}()}, \code{\link{SharedQuartetStatus}()}, \code{\link{SplitStatus}()} } diff --git a/man/QuartetStatus.Rd b/man/QuartetStatus.Rd index 3d671ed1..4a7abe3f 100644 --- a/man/QuartetStatus.Rd +++ b/man/QuartetStatus.Rd @@ -94,8 +94,8 @@ tips that do not occur in both trees being compared. \item \code{ManyToManyQuartetAgreement()}: Agreement of each quartet, comparing each pair of trees in a list. -\item \code{TwoListQuartetAgreement()}: Agreement of each quartet in trees in one list with -each quartet in trees in a second list. +\item \code{TwoListQuartetAgreement()}: Agreement of each quartet in trees in \code{trees1} with +each quartet in trees in \code{trees2}. \item \code{SingleTreeQuartetAgreement()}: Agreement of each quartet in trees in a list with the quartets in a comparison tree. @@ -135,7 +135,8 @@ QuartetDivergence(TwoListQuartetAgreement(sq_trees[1:3], sq_trees[10:13])) \itemize{ \item Use splits (groups/clades defined by nodes or edges of the tree) instead of quartets as the unit of comparison: \code{\link[=SplitStatus]{SplitStatus()}}. -\item Generate distance metrics from quartet statuses: \code{\link[=SimilarityMetrics]{SimilarityMetrics()}}. +\item Generate distance metrics from quartet statuses: \code{\link[=SimilarityMetrics]{SimilarityMetrics()}}, +\verb{[PairwiseQuartets()]}. } Other element-by-element comparisons: @@ -143,6 +144,7 @@ Other element-by-element comparisons: \code{\link{CompareQuartetsMulti}()}, \code{\link{CompareSplits}()}, \code{\link{PairSharedQuartetStatus}()}, +\code{\link{PairwiseQuartets}()}, \code{\link{QuartetState}()}, \code{\link{SplitStatus}()} } diff --git a/man/SplitStatus.Rd b/man/SplitStatus.Rd index 1698eb21..23bf88c3 100644 --- a/man/SplitStatus.Rd +++ b/man/SplitStatus.Rd @@ -92,6 +92,7 @@ Other element-by-element comparisons: \code{\link{CompareQuartetsMulti}()}, \code{\link{CompareSplits}()}, \code{\link{PairSharedQuartetStatus}()}, +\code{\link{PairwiseQuartets}()}, \code{\link{QuartetState}()}, \code{\link{SharedQuartetStatus}()} } diff --git a/tests/testthat/test-PairwiseQuartets.R b/tests/testthat/test-PairwiseQuartets.R new file mode 100644 index 00000000..a6799421 --- /dev/null +++ b/tests/testthat/test-PairwiseQuartets.R @@ -0,0 +1,6 @@ +test_that("PairwiseQuartets() works", { + expect_equal(PairwiseQuartets(sq_trees), + QuartetDivergence(ManyToManyQuartetAgreement(sq_trees))) + expect_equal(PairwiseQuartets(sq_trees, DoNotConflict), + DoNotConflict(ManyToManyQuartetAgreement(sq_trees))) +}) diff --git a/vignettes/Using-Quartet.Rmd b/vignettes/Using-Quartet.Rmd index 4e7407a1..4aa23610 100644 --- a/vignettes/Using-Quartet.Rmd +++ b/vignettes/Using-Quartet.Rmd @@ -131,6 +131,33 @@ status <- TwoListQuartetAgreement(forest[1:4], forest[5:6]) QuartetDivergence(status, similarity = FALSE) ``` +## Pairwise comparison + +To compute distances between all pairs of trees in a list, use the `PairwiseQuartets()` function: + +```{r allpairs} +PairwiseQuartets(forest) +# equivalent to QuartetDivergence(ManyToManyQuartetAgreement(forest)) +``` + +This function can help to summarise sets of trees: + +```{r treedist} +# Map distances between trees +forestDist <- PairwiseQuartets(forest) +mapping <- cmdscale(as.dist(forestDist)) +plot(mapping, asp = 1, axes = FALSE, frame.plot = FALSE, + xlab = "", ylab = "", col = seq_along(forest), type = "n") +text(mapping, names(forest)) + +# The TreeDist library is used to compute the median tree +if (requireNamespace("TreeDist", quietly = TRUE)) { + library("TreeDist") + # Plot the median tree: + plot(median(forest, distance = PairwiseQuartets)) +} +``` + ## Trees with different tip labels "Quartet" can compare trees of different sizes or with non-identical sets of