| Title: | Visualize Clade Recovery and Support Across Phylogenetic Trees |
| Version: | 0.1.0 |
| Description: | Generates rug plot visualizations directly on tree nodes to illustrate clade recovery and support from multiple phylogenetic and phylogenomic analyses. As modern studies routinely employ diverse datasets and inference techniques producing potentially conflicting trees, 'phylorug' simplifies the comparison among these trees by consolidating clade recovery and support on a reference tree. |
| License: | MIT + file LICENSE |
| URL: | https://github.com/mdrifathahamed/phylorug, https://mdrifathahamed.github.io/phylorug/ |
| BugReports: | https://github.com/mdrifathahamed/phylorug/issues |
| Depends: | R (≥ 4.1.0) |
| Imports: | ape, graphics, grDevices, phangorn, stats, tools, utils |
| Suggests: | knitr, mockery, rmarkdown, testthat (≥ 3.0.0) |
| Config/testthat/edition: | 3 |
| Encoding: | UTF-8 |
| LazyData: | true |
| RoxygenNote: | 8.0.0 |
| VignetteBuilder: | knitr |
| NeedsCompilation: | no |
| Packaged: | 2026-10-23 08:02:53 UTC; 1 |
| Author: | Md Rifath Ahamed |
| Maintainer: | Md Rifath Ahamed <rifathahamed777@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-11-06 16:50:02 UTC |
phylorug: Visualize Clade Recovery and Support Across Phylogenetic Trees
Description
Generates rug plot visualizations directly on tree nodes to illustrate
clade recovery and support from multiple phylogenetic and phylogenomic
analyses. See vignette("phylorug") for a detailed guide.
Core functions
read_treesRead tree files from disk
translate_tipsRename specimen codes to species names
check_taxaDiagnose taxon consistency across trees
prune_to_sharedPrune trees to shared taxa
node_presence_matrixBuild the presence/support matrix
plot_phylorugDraw the rug plot on a reference tree
add_treeAdd a tree to an existing matrix
Author(s)
Maintainer: Md Rifath Ahamed rifathahamed777@gmail.com (ORCID) [copyright holder]
Authors:
Md Rifath Ahamed rifathahamed777@gmail.com (ORCID) [copyright holder]
J. Salvador Arias js.arias@conicet.gov.ar (ORCID)
Sergei Tarasov sergei.tarasov@helsinki.fi (ORCID)
References
Wheeler, W.C. (1995). Sequence alignment, parameter sensitivity, and the phylogenetic analysis of molecular data. Systematic Biology, 44(3), 321-331. doi:10.1093/sysbio/44.3.321
Giribet, G. (2003). Stability in phylogenetic formulations and its relationship to nodal support. Systematic Biology, 52(4), 554-564. doi:10.1080/10635150390223730
Sanders, J.G. (2010). Program note: Cladescan, a program for automated phylogenetic sensitivity analysis. Cladistics, 26(1), 114-116. doi:10.1111/j.1096-0031.2009.00280.x
Machado, D.J. (2015). YBYRA facilitates comparison of large phylogenetic trees. BMC Bioinformatics, 16, 204. doi:10.1186/s12859-015-0642-9
Wolfe, J.M. et al. (2019). A phylogenomic framework, evolutionary timeline and genomic resources for comparative studies of decapod crustaceans. Proceedings of the Royal Society B, 286(1901), 20190079. doi:10.1098/rspb.2019.0079
Fu, Y. et al. (2025). Phylogenomic insights into the higher level relationships within Culicomorpha (Diptera). Insect Systematics and Diversity, 9(6), ixaf056. doi:10.1093/isd/ixaf056
Montanaro, G., Lopes, F. et al. (2026). Phylogenomics resolves a 200-year-old puzzle: a revised tribal classification of Afro-Eurasian dung beetles (Coleoptera: Scarabaeinae). bioRxiv. doi:10.64898/2026.07.22.740134
See Also
Useful links:
Report bugs at https://github.com/mdrifathahamed/phylorug/issues
Add a comparison tree to an existing node presence matrix
Description
Adds a new comparison tree to an existing node presence matrix without rerunning the whole pipeline from scratch. The function computes clade recovery (presence) and support for the new tree only and attaches the results as a new column in every matrix of the npm. All existing columns remain unchanged.
Usage
add_tree(
npm,
backbone,
new_tree,
name,
support_col = 1,
support_type = NULL,
pool_threshold = 1
)
Arguments
npm |
A node presence matrix list, as returned by
|
backbone |
The backbone tree used to create |
new_tree |
A |
name |
Character string. Column name for the new tree in the npm matrices. Required. Must be a single non-empty string and must not duplicate an existing column name. |
support_col |
Integer or vector of integers (max 3). Which support
value(s) to extract from the new tree's node labels, matching the
|
support_type |
Optional character string naming the support metric
of the new tree (e.g. |
pool_threshold |
Numeric between 0 and 1. Controls how pools are
scored. Default |
Details
Three taxon scenarios are handled automatically:
- Identical
The new tree shares all backbone taxa exactly. Every clade is evaluated normally.
- Superset
The new tree contains all backbone taxa plus extras. The extra taxa are pruned internally so that clade keys match the backbone's. Without this pruning, a backbone clade
(A, B)would fail to match a new-tree node grouping(A, B, X), producing a false absence. A message reports the pruning. The user's original tree object is not modified.- Missing
The new tree lacks one or more backbone taxa. Any backbone clade containing a missing taxon cannot be evaluated in this tree and is set to
NAin both the presence and support matrices. These appear as red ("not computed") cells in the rug plot. A message lists the missing taxa and suggests rebuilding the npm from scratch withprune_to_shared()if the red cells are undesirable. Unlikenode_presence_matrix(), which errors on missing taxa,add_tree()is deliberately permissive: when adding a tree after the initial analysis, different taxon sampling is a legitimate use case, not a data error.
The new tree must be rooted. If it is a multiPhylo object (a pool
of equally optimal trees from one search), clade presence is determined
by pool_threshold: the default (1.0, strict consensus) requires the
clade in every pool tree; 0.5 applies majority rule; 0 records the
raw proportion. Support extraction is skipped for pools because
averaging node labels across equally optimal trees is not scientifically
valid; support cells for that column will be NA. To include support
values from a parsimony analysis, compute the consensus tree with
bootstrap or jackknife support upstream (e.g. in TNT) and pass that
consensus as a single phylo object.
If support_type is supplied, it is appended to the "support_type"
attribute stored in the npm object, keyed by the new tree's name. This allows
plot_phylorug() to apply the correct metric-specific thresholds without the
user re-declaring the full vector.
Value
The updated npm list with the new tree appended as an additional
column in the presence matrix and each support_* matrix. The
"pool_sizes" attribute is updated, and "support_type" is extended
if the argument was supplied.
See Also
node_presence_matrix() to build the initial npm, plot_phylorug()
to visualise the result, and check_taxa() to diagnose taxon overlap
before adding.
Examples
# Build an npm with 3 of the 5 shipped trees:
backbone <- sample_trees[["70p_uce"]]
others <- sample_trees[c("70p_partition_entropy", "70p_ghost")]
npm <- node_presence_matrix(backbone, others)
ncol(npm$presence) # 2 comparison trees
# Add a fourth tree without re-running the pipeline:
npm <- add_tree(npm, backbone,
sample_trees[["70p_ASTRAL_uce"]],
name = "ASTRAL_uce")
ncol(npm$presence) # now 3
# Add the fifth tree from a file, with a declared support type.
# Here a shipped tree is first written to a temporary file; with your own
# data, pass the path to your tree file. The tree must be rooted
# (see ape::root()).
tree_file <- tempfile(fileext = ".tre")
ape::write.tree(sample_trees[["70p_ASTRAL_partition_entropy"]], tree_file)
new_tree <- ape::read.tree(tree_file)
npm <- add_tree(npm, backbone, new_tree,
name = "ASTRAL_part_entropy",
support_type = "lpp")
ncol(npm$presence) # now 4
attr(npm, "support_type")
unlink(tree_file)
Diagnose taxon consistency between backbone and comparison trees
Description
Checks whether the backbone and comparison trees share the same set of
taxa or not. If a comparison tree is missing a backbone taxon, every backbone
clade that includes that taxon would be falsely scored as absent,
node_presence_matrix() prevents this by stopping with an error, but
this function helps you diagnose the mismatch before that happens. If you
already know all trees share the same taxa, skip straight to
node_presence_matrix().
Usage
check_taxa(backbone, trees, verbose = TRUE)
Arguments
backbone |
The reference tree, as a |
trees |
A named list of |
verbose |
Logical. If |
Details
This function reports; it does not modify the trees. If the backbone is
present in comparison trees it is silently removed before comparison. Three
outcomes are
- identical
All comparison trees share the backbone's taxa exactly.
- superset
One or more comparison trees contain every backbone taxon plus additional taxa. All backbone clades can still be evaluated; the extra taxa are ignored by
node_presence_matrix().- missing
One or more comparison trees lack backbone taxa. A clade cannot be searched in a tree that does not contain all of its taxa, so
node_presence_matrix()will stop with an error. Useprune_to_shared()to reduce all trees to their common taxon set before building the matrix.
Where a comparison tree is a pool of several equally optimal trees, every tree in the pool is checked. A pool whose trees disagree about their own taxa is a data problem, and is an error.
Value
A single logical value: TRUE if every comparison tree shares the
backbone's taxa exactly. The value carries a "diagnostics" attribute, a
data frame with one row per comparison tree giving its status
("identical", "superset" or "missing") and the taxa missing from, or
extra to, the backbone. Diagnostics are attached whatever verbose is set
to.
See Also
read_trees() to load the trees, translate_tips() to
harmonize naming conventions, and prune_to_shared() to reduce
trees to a common taxon set.
Examples
# sample_trees is a named list of 5 phylo objects shipped with phylorug,
# the same structure you get from read_trees(). Pick one analysis as the
# backbone, and the rest as comparison trees:
backbone <- sample_trees[["70p_uce"]]
others <- sample_trees[names(sample_trees) != "70p_uce"]
# Diagnose taxon consistency (verbose = TRUE by default reports the outcome):
result <- check_taxa(backbone, others)
# If any tree is missing or has extra taxa, inspect the full report:
attr(result, "diagnostics")
Tabulate clade recovery and support across trees
Description
Compares a set of phylogenetic trees against a reference topology, the
"backbone". For each internal node of the backbone, the function asks
whether the same clade appears in each tree, and records either its presence
or its support value.
Usage
node_presence_matrix(
backbone,
trees,
support_col = 1,
support_type = NULL,
pool_threshold = 1
)
Arguments
backbone |
The reference tree, as a |
trees |
A named list of |
support_col |
Integer or vector of integers (max 3). Specifies which
value(s) to extract from multi-metric node labels. For example, if an
IQ-TREE tree stores SH-aLRT and UFBoot as "80/95", passing |
support_type |
Optional named character vector mapping comparison trees
to their support metrics (e.g. |
pool_threshold |
Numeric between 0 and 1. Controls how pools of
equally optimal trees are scored. |
Details
This is the core function of the phylorug pipeline. It can be called
directly after read_trees(). Running check_taxa() first is recommended
but not required node_presence_matrix() will stop with an error if any
comparison tree is missing backbone taxa.
Every tree must include the complete set of backbone taxa. Because a tree
lacking a backbone taxon cannot be assessed for the presence of a clade
containing that taxon, scoring such a clade as 'absent' would introduce a
false negative. The function therefore enforces strict taxon matching. Use
check_taxa() to diagnose the discrepancies and prune_to_shared() to
harmonize the backbone and comparison tree taxa.
The function always computes both a presence matrix and a support matrix
in a single pass. The plotting function plot_phylorug() decides which to
use based on the visualisation context.
The presence matrix records clade recovery: 1 where the bipartition
is found, 0 where absent. For multiple equally most parsimonious trees
(MPTs), the behaviour depends on pool_threshold: the default (1.0,
strict consensus) requires the clade to appear in every pool tree;
0.5 applies majority rule; 0 records the raw proportion.
Each support_* matrix records the raw support value from the node label of
the tree that recovered the clade (e.g. bootstrap, posterior probability).
Support values are not computed for pools of equally optimal trees
(multiPhylo), only presence mode is available for these, and their support
cells will be NA. If you need support mode for a parsimony analysis, build
a consensus tree with support values mapped onto it (e.g. bootstrap on the
strict consensus) in your upstream analysis, and pass that single tree to
phylorug instead.
Value
A named list with one row per internal backbone node and one column per comparison tree:
- presence
Clade presence:
1where recovered,0where absent. For pools, the value depends onpool_threshold(see above).
\item{support matrices}{One matrix per value in `support_col`
(named `support_1`, `support_2`, etc.). Raw support values where
the clade was recovered, `NA` where absent or where the clade was
recovered but no support value could be parsed from the node label.}
See Also
check_taxa() to diagnose taxon mismatches before building
the matrix, plot_phylorug() to visualize the result, and
add_tree() to append additional comparison trees to an existing
matrix without recomputing it from scratch.
Examples
# phylorug ships `sample_trees`: a named list of 5 phylo objects (beetles),
# the same structure you get from read_trees(). Just type `sample_trees`.
# Pick one analysis as the backbone, and the rest as comparison trees:
backbone <- sample_trees[["70p_uce"]]
others <- sample_trees[names(sample_trees) != "70p_uce"]
# Optional: diagnose taxon overlap before building the matrix.
# This is not required, node_presence_matrix() enforces matching internally.
check_taxa(backbone, others)
# --- Presence/absence matrix -----------------------------------------------
# Just pass the backbone and comparison trees (support_col defaults to 1).
# For pools of MPTs, pool_threshold defaults to 1.0 (strict consensus):
npmatrix <- node_presence_matrix(backbone, others)
npmatrix$presence # clade presence/absence (1/0)
npmatrix$support_1 # support values (from column 1 of the node labels)
# --- Multiple support metrics at once --------------------------------------
# IQ-TREE stores SH-aLRT and UFBoot2 as "80/95". Pass their column positions
# to support_col to extract both in a single pass:
rugmt <- node_presence_matrix(backbone, others, support_col = c(1, 2))
rugmt$support_1 # first metric (SH-aLRT)
rugmt$support_2 # second metric (UFBoot2)
# --- With support_type (stored in npm, used by plot_phylorug) --------------
# Declaring support_type lets plot_phylorug() apply metric-specific
# thresholds automatically. If omitted, universal 0-1 thresholds are used.
support_type <- c(
"70p_ASTRAL_partition_entropy" = "lpp",
"70p_ASTRAL_uce" = "lpp",
"70p_ghost" = "ufboot",
"70p_partition_entropy" = "ufboot"
)
npm_typed <- node_presence_matrix(backbone, others,
support_type = support_type)
attr(npm_typed, "support_type") # stored as an attribute
Parse support values from internal nodes of a phylogenetic tree
Description
Extracts the node labels of one tree and returns their support values as a
data frame: one row per internal node, three columns (support_1,
support_2, support_3). How a label fills those columns:
A single value (such as an IQ-TREE bootstrap) fills
support_1; the other two areNA.A compound label split by
sep(default/) fills one column per value:Two for IQ-TREE SH-aLRT/UFBoot2 or ASTRAL pp1/pp2.
Three for IQ-TREE SH-aLRT/UFBoot2/aBayes or ASTRAL pp1/pp2/pp3.
Empty or non-numeric pieces become
NA.A tree with no node labels returns a data frame of all
NA.
Usage
node_support(tree, sep = "/", digits = NULL)
Arguments
tree |
A phylogenetic tree of class |
sep |
A single character string giving the delimiter that separates
compound support values. Defaults to |
digits |
Integer or |
Value
A data frame with three columns, support_1, support_2 and
support_3, and one row per internal node of the tree. Columns not present
in a given label are NA.
Draw the rug at every internal node of a plotted tree
Description
For each internal node of the backbone tree, paints a small grid of rectangles, one per comparison tree, showing whether that tree recovered the node's clade and, in support mode, how strongly. Together these grids are the rug.
The appearance is set by a tier, resolved from which arguments are supplied
rather than named directly. (plot_phylorug() selects the tier for the user
through its mode argument.)
Tier 1, presence:
supportisNULL. Cells are black for present and white for absent. Grey cells appear only whenpool_threshold = 0was used innode_presence_matrix(), indicating partial recovery across a pool of equally optimal trees.Tier 2, support:
supportis non-NULL. Recovered cells are shaded by binned support strength, black (very high) through three progressively lighter greys down to low. A cell is white when the tree does not recover the clade at all, and red when the tree recovers the clade but carries no support value for it.
Users do not call this directly; plot_phylorug() calls it after drawing the
tree and working out the cell geometry.
Usage
plot_node_rug(
npm,
support = NULL,
support_type = NULL,
thresholds = NULL,
cell_h,
cell_w,
n_cols,
x_offset = 0,
y_offset = 0,
rug_position = c("inside", "outside"),
border_lwd = 0.2,
last_pp = NULL
)
Arguments
npm |
The presence matrix from |
support |
Support matrix of the same shape as |
support_type |
Named character vector mapping each comparison tree to
its support measure (e.g. |
thresholds |
Optional list overriding the built-in bin thresholds, keyed
by support type. |
cell_h, cell_w |
Numeric. Height and width of one cell, in the tree's plotting coordinates. |
n_cols |
Integer. Columns in each node's grid. |
x_offset, y_offset |
Numeric. Shift the whole grid away from the node, as a fraction of the tree's width and height. |
rug_position |
One of |
border_lwd |
Line width of the neutral grey border drawn around every
cell. Default |
last_pp |
Plot coordinates from |
Value
invisible(NULL). Called internally by plot_phylorug() to
handle cell-level drawing and geometry at each node.
Draw a phylorug: a backbone tree with rug plots on every internal node
Description
plot_phylorug() overlays rug plots on a backbone phylogeny, compares how
multiple analyses treat each internal node. In presence mode, cells are black
(recovered) or white (absent). In support mode, cells are shaded by binned
support strength. The function handles canvas sizing, legend placement, and
font scaling automatically.
Usage
plot_phylorug(
backbone,
npm,
file = NULL,
width = NULL,
height = NULL,
mode = c("presence", "support"),
support_idx = 1,
thresholds = NULL,
n_rows = NULL,
n_cols = NULL,
include_backbone = FALSE,
nodes = NULL,
legend = TRUE,
show_support = TRUE,
show_support_idx = NULL,
cell_scale = 0.45,
x_offset = 0,
y_offset = 0,
rug_position = c("inside", "outside"),
dot_identical = TRUE,
dot_col = "black",
dot_cex = NULL,
support_label_cex = NULL,
support_label_col = "red",
dot_on_very_high = TRUE,
hide_unsupported = TRUE,
...
)
Arguments
backbone |
A |
npm |
A named list containing the |
file |
Optional character string specifying the output file name or full
directory path. If left as |
width, height |
Numeric. Optional canvas dimensions in inches, applied
only when exporting to a |
mode |
One of |
support_idx |
Integer (1, 2, or 3). Default is |
thresholds |
Optional list overriding the built-in bin thresholds
used in support mode. Support values are binned into four levels: very
high, high, moderate, and low. Each entry supplies the lower bounds for
the top three levels as a named numeric vector with exactly three names:
|
n_rows, n_cols |
Integer. Grid shape for the rug at each node. If
|
include_backbone |
Logical or character. If |
nodes |
Optional. Restricts the plot to specific backbone nodes. Three ways to specify:
If |
legend |
Logical. Default |
show_support |
Logical. If |
show_support_idx |
Optional. Controls what appears in the label on the tree AND what the legend calls it. Accepts several shapes:
Recognised metric keys for named-integer form: |
cell_scale |
Numeric multiplier on cell height. Default 0.45. |
x_offset, y_offset |
Numeric grid shift. Default 0. |
rug_position |
One of |
dot_identical |
Logical. Default |
dot_col, dot_cex |
Colour and size of the identical-clade dot. Defaults
are |
support_label_cex |
Numeric or |
support_label_col |
Colour of the backbone support labels. Default
|
dot_on_very_high |
Logical. Default |
hide_unsupported |
Logical. Default |
... |
Additional arguments passed to |
Details
Each internal node is drawn as either a dot (compact summary) or a rug
plot (full per-analysis grid). What a dot means depends on the mode. In
presence mode, a dot means every comparison analysis recovered the clade;
control this with dot_identical, setting it to FALSE to show rug
plots on every node, even unanimous ones. In support mode, a dot means
every comparison analysis recovered the clade and every one independently
rates it very-high support, control this with dot_on_very_high, setting it
to FALSE to show rug plots on every node regardless of support level. Dot
appearance (dot_col, dot_cex) is shared across both modes.
Value
Invisibly, the file path if a file was written, or NULL if plotted
directly to the active graphics device.
See Also
node_presence_matrix() to build the input data,
check_taxa() to verify taxon sets, and
add_tree() to append trees to an existing matrix.
Examples
# Build the plotting input from real trees:
backbone <- sample_trees[["70p_uce"]]
others <- sample_trees[names(sample_trees) != "70p_uce"]
support_type <- c(
"70p_ASTRAL_partition_entropy" = "lpp",
"70p_ASTRAL_uce" = "lpp",
"70p_ghost" = "ufboot",
"70p_partition_entropy" = "ufboot"
)
npm_st <- node_presence_matrix(backbone, others,
support_col = 1,
support_type = support_type)
# --- Presence mode --------------------------------------------------------
# Each cell shows whether an analysis recovered the backbone clade.
tmp <- tempfile(fileext = ".pdf")
plot_phylorug(backbone, npm_st, file = tmp)
unlink(tmp)
# --- Support mode ---------------------------------------------------------
tmp2 <- tempfile(fileext = ".pdf")
plot_phylorug(backbone, npm_st,
file = tmp2,
mode = "support",
support_idx = 1)
unlink(tmp2)
# --- Some optional controls -----------------------------------------------
tmp3 <- tempfile(fileext = ".pdf")
plot_phylorug(backbone, npm_st,
file = tmp3,
include_backbone = TRUE,
rug_position = "outside")
unlink(tmp3)
# --- Restrict to specific nodes -------------------------------------------
# By taxa: name two or more tips whose MRCA is the node you want.
# Useful when you know which species define a clade of interest.
tmp4 <- tempfile(fileext = ".pdf")
plot_phylorug(backbone, npm_st,
file = tmp4,
nodes = list(c("Sisyphus_schaefferi_STL44",
"Sisyphus_muricatus__STL5")))
unlink(tmp4)
# By node ID: useful when exploring interactively after inspecting
# rownames(npm_st$presence) or ape::nodelabels() output.
tmp5 <- tempfile(fileext = ".pdf")
plot_phylorug(backbone, npm_st,
file = tmp5,
nodes = as.integer(rownames(npm_st$presence))[1:2])
unlink(tmp5)
Trim the backbone and its comparison trees to their shared set of taxa
Description
First finds the taxa that the backbone and all comparison trees share, then trims everything else from the backbone and from every comparison tree.
Usage
prune_to_shared(backbone, trees, verbose = TRUE)
Arguments
backbone |
A phylogenetic tree of class |
trees |
A named list of |
verbose |
Logical. If |
Details
A clade cannot be compared across trees that were not run on the same
taxa. Where a comparison tree is missing a backbone taxon, every
backbone clade containing that taxon becomes unevaluable in that tree, and
node_presence_matrix() refuses to proceed. Trimming to the shared taxa
resolves this by making every tree contain the same taxa.
The cost is that the questions become narrower. Any clade containing a
dropped taxon no longer exists on the backbone and cannot be reported, even
where most comparison trees recovered it. Check the report from
check_taxa() before trimming: if only one or two taxa are involved the loss
is minimal, but if several comparison trees each lack a different taxon, the
shared set can shrink quickly.
Value
A list with two elements: backbone, the pruned backbone tree, and
trees, the pruned comparison trees, retaining their names and their
original single-tree or pooled structure. The list carries a "dropped"
attribute naming the taxa that were removed.
See Also
check_taxa() to see which taxa are missing and from where, before
deciding to prune.
Examples
# Build a backbone and comparison trees that do NOT all share the same taxa,
# so there is something to trim. (In practice these come from read_trees().)
backbone <- ape::read.tree(
text = "((((A,B),(C,D)),((E,F),(G,H))),(I,J));"
)
others <- list(
# All ten taxa, same as the backbone:
tree_1 = ape::read.tree(text = "((((A,B),(C,D)),((E,F),(G,H))),(I,J));"),
# Missing J:
tree_2 = ape::read.tree(text = "((((A,B),(C,D)),((E,F),(G,H))),I);"),
# Missing I:
tree_3 = ape::read.tree(text = "((((A,B),(C,D)),((E,F),(G,H))),J);")
)
# See which taxa are missing, and from which trees, before trimming:
check_taxa(backbone, others)
# Trim the backbone and every comparison tree to their shared taxa:
shared <- prune_to_shared(backbone, others)
# Which taxa were dropped:
attr(shared, "dropped")
# The pruned trees are ready for node_presence_matrix():
shared$backbone
shared$trees
Import phylogenetic trees from a directory
Description
Scans a directory for phylogenetic tree files, parses each one, and returns them as a named list. Format is detected from file content, so a directory may mix Newick and NEXUS files.
Usage
read_trees(
dir = ".",
ext = c("tre", "tree", "treefile", "nwk", "newick", "nex", "nexus", "contree"),
format = c("auto", "newick", "nexus"),
verbose = TRUE
)
Arguments
dir |
Path to the directory containing the tree files. Defaults to the working directory. |
ext |
Character vector of file extensions to look for, without the
leading dot (e.g. |
format |
The parsing strategy to use. Defaults to |
verbose |
Logical. If |
Details
Each file is one analysis. A file holding a single tree is returned as a
"phylo" ; a file holding several equally optimal trees from one search
(as from POY, TNT, or PAUP*) is returned as a "multiPhylo" and is
scored as a pool. How many pool trees must recover a clade before it
counts as present is controlled by the pool_threshold argument in
node_presence_matrix().
Do not supply posterior samples, bootstrap replicates, or sets of gene trees. These are distributions rather than analyses and must be summarised in the upstream analysis before use (e.g. into a consensus tree). Files holding more than 100 trees are rejected with an error.
Support values stored as numeric node labels in the tree file (e.g.
((A,B)95,(C,D)100);) are read normally. BEAST-style bracket
annotations ([&posterior=0.98]) are discarded by ape; the
topology is unaffected, and a message is emitted. Support values are imported
exactly as written in the tree file; read_trees() does not recompute or
verify them.
Files matching ext that contain no tree, such as a NEXUS character
matrix, are skipped with a message. A tree file that fails to parse is an
error.
Value
A named list, one element per tree file, named after the file names
with extensions removed. Single-tree files yield "phylo" objects;
multi-tree files yield "multiPhylo". Carries a "pool_sizes"
attribute giving the number of trees per analysis.
Examples
# phylorug ships example raw tree files in its `extdata` directory.
# Point read_trees() at one of those folders:
dir <- system.file("extdata", "beetles_70p", package = "phylorug")
# With only the directory, read_trees() detects each file's format from its
# contents (NEXUS or Newick, the two formats this version supports) and
# matches the default extension filter (tre, tree, treefile, nwk, ...).
trees <- read_trees(dir)
# The result is a named list, one element per analysis, ready to pass to
# [check_taxa()] or [node_presence_matrix()]:
names(trees)
# If a folder holds many files and you want only some, narrow `ext`
# to one extension, or to a set of them:
trees <- read_trees(dir, ext = "tre")
trees <- read_trees(dir, ext = c("tre", "tree", "treefile"))
# For full control you can also force a single parser. Note this applies
# one format to every matched file, so a file of a different format would
# not be read.
trees <- read_trees(dir, format = "newick")
Sample beetle phylogenies (15-taxon subset)
Description
A named list (the same structure returned by read_trees()) of five
phylogenetic trees from a dung beetle phylogenomic study, Montanaro,
Lopes et al. (2026), pruned to 15 taxa for compact demonstration of
the phylorug workflow. The trees are already rooted, outgroup-removed, and
tip labels translated from museum codes to species names. Users can select a
backbone tree and comparison trees, then pass them directly to
check_taxa(), node_presence_matrix() and plot_phylorug().
Usage
sample_trees
Format
A named list of 5 objects of class "phylo", each with 15 tips. Node
labels contain support values: SH-aLRT/UFBoot2 for IQ-TREE trees and local
posterior probability for ASTRAL trees.
Details
The five trees represent independent phylogenomic analyses of the same set of taxa using different inference methods and data types:
- 70p_uce
IQ-TREE maximum likelihood analysis of ultraconserved element (UCE) data. Recommended as the backbone tree.
- 70p_partition_entropy
IQ-TREE maximum likelihood analysis of partitioned sequence data.
- 70p_ghost
IQ-TREE GHOST heterotachous model on partitioned data.
- 70p_ASTRAL_uce
ASTRAL coalescent analysis of UCE gene trees.
- 70p_ASTRAL_partition_entropy
ASTRAL coalescent analysis of partitioned gene trees.
Source
Montanaro, G., Lopes, F., Gunter, N.L., et al. (2026). Phylogenomics resolves a 200-year-old puzzle: a revised tribal classification of Afro-Eurasian dung beetles (Coleoptera: Scarabaeinae). bioRxiv. doi:10.64898/2026.07.22.740134
Examples
# Core pipeline:
backbone <- sample_trees[["70p_uce"]]
others <- sample_trees[names(sample_trees) != "70p_uce"]
# Optional: diagnose taxon overlap
check_taxa(backbone, others)
npm <- node_presence_matrix(backbone, others, support_col = c(1, 2))
tmp <- tempfile(fileext = ".pdf")
plot_phylorug(backbone, npm, file = tmp)
unlink(tmp)
Relabel tips across a list of trees using a lookup table
Description
Translates tip labels of each tree in a list using a lookup table supplied as a data frame. This function is optional in the phylorug workflow, use it only if your tip labels are specimen codes, accession numbers, or any other identifiers that need converting to a different format, such as scientific species names.
If your tip labels are already in the correct format, skip this step and
proceed directly to node_presence_matrix(). Only tips with a matching entry
in from_col are replaced with the corresponding value in to_col.
Unmatched tips are left unchanged. This function modifies only the
tip.label field of each tree. Tree topology, branch lengths, and node
labels are unaffected.
Usage
translate_tips(trees, data, from_col, to_col, verbose = TRUE)
Arguments
trees |
A named list of |
data |
A data frame containing the label translation lookup table. Can
be a standard |
from_col |
A character string naming the column in |
to_col |
A character string naming the column in |
verbose |
Logical. If |
Value
A named list of "phylo" objects identical in structure to trees,
with matching tip labels replaced according to data. Tree topology and
edge lengths remain unchanged.
Examples
# Example trees and a lookup table ship inside phylorug, so we first read
# them into the environment, then tell translate_tips() which column holds
# the current labels and which holds the replacements:
dir <- system.file("extdata", "beetles_50p", package = "phylorug")
file <- system.file("extdata", "beetles_50p", "biogeo.csv",
package = "phylorug")
trees <- read_trees(dir)
dict <- utils::read.csv(file)
# Relabel tips from specimen codes to species names. The message reports how
# many tips were translated and how many were left unchanged in each tree:
translated <- translate_tips(trees, dict,
from_col = "specimen_code",
to_col = "species_name")