Skip to content

Commit dca5918

Browse files
committed
Merge branch 'main' into transfer-consensus
2 parents 9e01c6e + a971e42 commit dca5918

File tree

17 files changed

+322
-37
lines changed

17 files changed

+322
-37
lines changed

.github/workflows/ASan.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
ASAN_OPTIONS: detect_container_overflow=1:verify_asan_link_order=0
5050

5151
steps:
52-
- uses: actions/checkout@v5
52+
- uses: actions/checkout@v6
5353

5454
- name: Initialize ASan configuration
5555
run: |

.github/workflows/R-CMD-check.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252

5353
steps:
5454
- name: Checkout git repo
55-
uses: actions/checkout@v5
55+
uses: actions/checkout@v6
5656

5757
- name: Temporarily bump package version
5858
run: |
@@ -112,7 +112,7 @@ jobs:
112112

113113
steps:
114114
- name: Checkout git repo
115-
uses: actions/checkout@v5
115+
uses: actions/checkout@v6
116116

117117
- name: Temporarily bump package version
118118
run: |
@@ -246,12 +246,12 @@ jobs:
246246

247247
steps:
248248
- name: Checkout PR branch
249-
uses: actions/checkout@v5
249+
uses: actions/checkout@v6
250250
with:
251251
path: pr
252252

253253
- name: Checkout target branch
254-
uses: actions/checkout@v5
254+
uses: actions/checkout@v6
255255
with:
256256
ref: ${{ github.event.pull_request.base.ref || 'main' }}
257257
path: main
@@ -301,14 +301,14 @@ jobs:
301301

302302
- name: Upload PR benchmark results
303303
if: failure()
304-
uses: actions/upload-artifact@v4
304+
uses: actions/upload-artifact@v6
305305
with:
306306
name: pr-benchmark-results
307307
path: pr/pr-benchmark-results/*.bench.Rds
308308

309309
- name: Upload main benchmark results
310310
if: failure()
311-
uses: actions/upload-artifact@v4
311+
uses: actions/upload-artifact@v6
312312
with:
313313
name: main-benchmark-results
314314
path: pr/main-benchmark-results/*.bench.Rds

.github/workflows/copilot-setup-steps.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
# If you do not check out your code, Copilot will do this for you.
2727
steps:
2828
- name: Checkout code
29-
uses: actions/checkout@v4
29+
uses: actions/checkout@v6
3030

3131
- name: Set up R
3232
uses: r-lib/actions/setup-r@v2
@@ -55,7 +55,7 @@ jobs:
5555
check
5656
5757
- name: Checkout TreeTools source (for debugging support)
58-
uses: actions/checkout@v4
58+
uses: actions/checkout@v6
5959
with:
6060
repository: ms609/TreeTools
6161
path: TreeTools-source

.github/workflows/pkgdown.yml

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,27 @@ jobs:
3636
- name: Export Shinylive app
3737
shell: Rscript {0}
3838
run: |
39-
# ── Pin shiny to pre-otel version ──
40-
# otel (OpenTelemetry) became a hard Import of shiny in 1.12.0,
41-
# but otel is not yet available as a WebAssembly binary on
42-
# repo.r-wasm.org. shinylive resolves deps from the LOCAL
43-
# library, so the installed shiny's otel dep causes a download
44-
# failure. Pin to the last CRAN release without otel.
45-
#
46-
# TODO: Remove this pin once otel appears at
47-
# http://repo.r-wasm.org/bin/emscripten/contrib/4.4/PACKAGES
39+
# ── Use dev shinylive for R 4.5 WASM support ──
40+
# CRAN shinylive 0.3.0 targets webR R 4.4.1.
41+
# The dev version (0.3.0.9000) targets R 4.5.1, where:
42+
# - otel is available on repo.r-wasm.org
43+
# - R-universe has a fixed TreeTools (no RCurl dep)
44+
# TODO: Switch back to CRAN shinylive once 0.4.0 ships.
45+
remotes::install_github("posit-dev/r-shinylive", quiet = TRUE)
4846
47+
# ── Install TreeTools and TreeDist from R-universe ──
48+
# repo.r-wasm.org has TreeTools 2.0.0 (still imports RCurl) for
49+
# both R 4.4 and 4.5. R-universe has 2.2.0.9001 (RCurl moved to
50+
# Suggests) compiled for R 4.5. Setting Repository to the
51+
# R-universe URL makes shinylive fetch the WASM binary from there.
52+
# Similarly, installing TreeDist from R-universe avoids the version
53+
# mismatch warning (local dev != WASM 2.9.2 on repo.r-wasm.org).
54+
# TODO: Remove once TreeTools >= 2.2.0 and TreeDist >= 2.13.0
55+
# are on CRAN and r-wasm.org has rebuilt them.
4956
install.packages(
50-
"https://cran.r-project.org/src/contrib/Archive/shiny/shiny_1.11.1.tar.gz",
51-
repos = NULL, type = "source"
57+
c("TreeTools", "TreeDist"),
58+
repos = c("https://ms609.r-universe.dev",
59+
"https://cloud.r-project.org")
5260
)
5361
5462
# ── Work around shinylive bug (coatless/quarto-webr#228) ──
@@ -94,18 +102,16 @@ jobs:
94102
)
95103
96104
# ── Export ──
97-
if (!requireNamespace("shinylive", quietly = TRUE)) {
98-
install.packages("shinylive")
99-
}
100105
tryCatch(
101106
shinylive::export(appdir = app_dir, destdir = "docs/app"),
102107
error = function(e) {
103108
msg <- conditionMessage(e)
104109
message("\n===== shinylive::export() failed =====")
105110
message(msg)
106-
message("This is often caused by a dependency that is not")
107-
message("available as a WebAssembly binary. Check:")
108-
message(" http://repo.r-wasm.org/bin/emscripten/contrib/4.4/PACKAGES")
111+
message("This is often caused by a dependency not available")
112+
message("as a WebAssembly binary. Check both:")
113+
message(" https://repo.r-wasm.org/bin/emscripten/contrib/4.5/PACKAGES")
114+
message(" https://ms609.r-universe.dev/bin/emscripten/contrib/4.5/PACKAGES")
109115
stop(e)
110116
}
111117
)

.github/workflows/update-csl.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
update-csl:
1414
runs-on: ubuntu-latest
1515
steps:
16-
- uses: actions/checkout@v5
16+
- uses: actions/checkout@v6
1717

1818
- name: Download latest CSL file
1919
run: |

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: TreeDist
22
Title: Calculate and Map Distances Between Phylogenetic Trees
3-
Version: 2.13.0
3+
Version: 2.13.0.9001
44
Authors@R: c(person("Martin R.", "Smith",
55
email = "martin.smith@durham.ac.uk",
66
role = c("aut", "cre", "cph", "prg"),

NEWS.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!-- AI-generated branch summary (2026-03-22) -->
2-
# Branch: `expose-lapjv` → merge target: `master`
2+
# Branch: `transfer-consensus` → merge target: `main`
33

44
This branch exposes the LAPJV (Jonker–Volgenant) linear assignment solver
55
via C++ headers so that downstream packages can link to it (`LinkingTo`),
@@ -8,7 +8,7 @@ and implements a transfer consensus method (`TransferConsensus()`,
88
`Rcpp::stop()` / `Rf_error()` calls out of C++ implementation code
99
into R-level input validation.
1010

11-
# TreeDist 2.13.0.9000
11+
# TreeDist 2.13.0.9001
1212

1313
This branch implements transfer consensus trees (`TransferConsensus()`) and
1414
a corresponding transfer distance metric (`TransferDist()`), providing a
@@ -18,6 +18,14 @@ inputs at the R level rather than using `Rcpp::stop()` or `Rf_error()` in
1818
implementation code.
1919
<!-- end AI-generated summary -->
2020

21+
## Performance
22+
23+
- `RobinsonFoulds()` now uses a fast C++ batch path for cross-distance
24+
computations (tree list vs tree list), matching the existing all-pairs
25+
batch performance. Previously, cross-distance calls fell through to
26+
per-pair R dispatch (~27× slower per pair); the new path achieves ~21×
27+
speedup on typical inputs (e.g. 50 × 250 trees, 50 tips).
28+
2129
# TreeDist 2.13.0 (2026-03-17)
2230

2331
## New features

R/RcppExports.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ robinson_foulds_all_pairs <- function(tables) {
1313
.Call(`_TreeDist_robinson_foulds_all_pairs`, tables)
1414
}
1515

16+
robinson_foulds_cross_pairs <- function(tables_a, tables_b) {
17+
.Call(`_TreeDist_robinson_foulds_cross_pairs`, tables_a, tables_b)
18+
}
19+
1620
consensus_info <- function(trees, phylo, p) {
1721
.Call(`_TreeDist_consensus_info`, trees, phylo, p)
1822
}

R/tree_distance_rf.R

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,43 @@ RobinsonFoulds <- function(tree1, tree2 = NULL, similarity = FALSE,
148148
class = "dist")
149149
}
150150
} else {
151-
unnormalized <- CalculateTreeDistance(RobinsonFouldsSplits, tree1, tree2,
152-
reportMatching)
153-
if (similarity) {
154-
unnormalized <- .MaxValue(tree1, tree2, NSplits) - unnormalized
151+
# Fast cross-pairs path: batch C++ via ClusterTable (Day 1985).
152+
# Only applicable when both inputs are lists of trees with matching
153+
# tip labels and reportMatching is not requested.
154+
fast <- NULL
155+
if (!reportMatching &&
156+
!inherits(tree1, c("phylo", "Splits")) &&
157+
!inherits(tree2, c("phylo", "Splits")) &&
158+
is.null(getOption("TreeDist-cluster"))) {
159+
lab1 <- TipLabels(tree1)
160+
lab2 <- TipLabels(tree2)
161+
if (is.list(lab1)) lab1 <- lab1[[1]]
162+
if (is.list(lab2)) lab2 <- lab2[[1]]
163+
if (setequal(lab1, lab2)) {
164+
ct1 <- as.ClusterTable(tree1, tipLabels = lab1)
165+
ct2 <- as.ClusterTable(tree2, tipLabels = lab1)
166+
shared <- robinson_foulds_cross_pairs(
167+
if (is.list(ct1)) ct1 else list(ct1),
168+
if (is.list(ct2)) ct2 else list(ct2)
169+
)
170+
splits1 <- NSplits(tree1)
171+
splits2 <- NSplits(tree2)
172+
if (similarity) {
173+
fast <- shared + shared
174+
} else {
175+
fast <- outer(splits1, splits2, "+") - shared - shared
176+
}
177+
dimnames(fast) <- list(names(tree1), names(tree2))
178+
}
179+
}
180+
if (is.null(fast)) {
181+
unnormalized <- CalculateTreeDistance(RobinsonFouldsSplits, tree1, tree2,
182+
reportMatching)
183+
if (similarity) {
184+
unnormalized <- .MaxValue(tree1, tree2, NSplits) - unnormalized
185+
}
186+
} else {
187+
unnormalized <- fast
155188
}
156189
}
157190

R/tree_information.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ consensus_info <- function(trees, phylo, p) {
428428
#' }
429429
#'
430430
#' @template MRS
431+
#' @family summary trees
431432
#' @importFrom TreeTools as.Splits SplitFrequency
432433
#' @export
433434
MCITree <- function(trees, info = "phylogenetic", check.tips = TRUE) {

0 commit comments

Comments
 (0)