The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
EN: This vignette documents the complete interactive
workflow for Bayesian species delimitation using bGMYC4. It guides you
through data selection, tree preprocessing (BEAST2 annotations),
interactive MCMC diagnostics with parameter auto-tuning, multi-tree
uncertainty pooling via parallel computing, and custom interactive
visualization. RU: Эта виньетка описывает полный
интерактивный рабочий процесс байесовской делимитации видов с помощью
bGMYC4. Она проведёт вас через выбор данных, предобработку деревьев
(аннотации BEAST2), интерактивную диагностику MCMC с автонастройкой
параметров, усреднение филогенетической неопределённости через
параллельные вычисления и кастомную интерактивную визуализацию.
—
EN: Load required libraries and define safe input
handlers. The workflow automatically cleans BEAST2 annotations, checks
ultrametricity, and validates parameter bounds.
RU: Загрузка библиотек и определение безопасных
обработчиков ввода. Рабочий процесс автоматически очищает аннотации
BEAST2, проверяет ультраметричность и валидирует границы параметров.
compiler::enableJIT(3) # JIT acceleration / Ускорение JIT
library(ape)
library(bGMYC4)
library(treeio)
library(ggtree)
library(dplyr)
library(plotly)
library(htmlwidgets)
library(future)
library(future.apply)
library(mcmcse)
# EN: Safe numeric scalar input / Безопасный ввод скалярных значений
input_scalar <- function(label, default_val) {
if (!interactive()) return(default_val)
val <- readline(sprintf(" %s (default / по умолчанию: %s): ", label, default_val))
if (nchar(trimws(val)) == 0) return(default_val)
num <- suppressWarnings(as.numeric(val))
if (is.na(num)) return(default_val)
return(num)
}
# EN: Safe numeric vector input / Безопасный ввод векторов
input_vector <- function(label, default_vec) {
if (!interactive()) return(default_vec)
val <- readline(sprintf(" %s (comma-separated, default / через запятую, по умолчанию: %s): ",
label, paste(default_vec, collapse = ", ")))
if (nchar(trimws(val)) == 0) return(default_vec)
nums <- suppressWarnings(as.numeric(unlist(strsplit(val, "[,;\\s]+"))))
nums <- nums[!is.na(nums)]
if (length(nums) != length(default_vec)) return(default_vec)
return(nums)
}
# EN: Enforce ultrametricity / Обеспечение ультраметричности
fix_ultrametric <- function(tr) {
if (!is.ultrametric(tr)) {
tr$edge.length <- round(tr$edge.length, 8)
if (!is.ultrametric(tr)) stop("❌ Tree remains non-ultrametric / Дерево остаётся неультраметричным.")
}
return(tr)
}EN: Load consensus tree with BEAST2 annotations (for
posterior visualization).
RU: Загрузка консенсусного дерева с аннотациями BEAST2
(для визуализации posterior).
consensus_path <- if (interactive()) readline("📥 Path to consensus tree / Путь к консенсусному дереву (.tree): ") else "dummy.tree"
posterior_path <- if (interactive()) readline("📥 Path to posterior trees / Путь к набору деревьев (.trees): ") else "dummy.trees"
tree_beast <- treeio::read.beast(consensus_path)
tree_consensus <- tree_beast@phylo
all_trees <- read.nexus(posterior_path)
class(all_trees) <- "multiPhylo"
# EN: Analysis Mode Selection / Выбор режима анализа
mode_str <- if (interactive()) readline("Mode 1 (Single) or 2 (Multi)? / Режим 1 или 2? [2]: ") else "2"
analysis_mode <- ifelse(nchar(trimws(mode_str)) == 0, 2, as.integer(mode_str))
# EN: Tree sampling with burnin / Выборка деревьев с учетом burnin
if (analysis_mode == 2) {
n_total <- length(all_trees)
burnin_idx <- floor(n_total * 0.10) # 10% burnin
n_sample <- input_scalar("Number of trees to sample / Кол-во деревьев", 10)
set.seed(42)
trees_sample <- all_trees[sample((burnin_idx + 1):n_total, n_sample)]
class(trees_sample) <- "multiPhylo"
} else {
trees_sample <- NULL
}
# EN: Outgroup removal via regex patterns / Удаление аутгрупп по паттернам
if (interactive() && tolower(readline("Drop outgroups? / Удалять аутгруппы? (y/n): ")) == "y") {
og_str <- readline("Enter patterns (comma-separated) / Введите паттерны: ")
og_patterns <- trimws(unlist(strsplit(og_str, "[,;]+")))
matching_tips <- unique(unlist(lapply(og_patterns, function(p) {
pattern <- paste0("(^|[^A-Za-z0-9])", p, "($|[^A-Za-z0-9])")
tree_consensus$tip.label[grepl(pattern, tree_consensus$tip.label, ignore.case = TRUE, perl = TRUE)]
})))
if (length(matching_tips) > 0) {
tree_consensus <- drop.tip(tree_consensus, matching_tips)
if (analysis_mode == 2) {
trees_sample <- lapply(trees_sample, drop.tip, tip = matching_tips)
class(trees_sample) <- "multiPhylo"
}
tree_beast <- treeio::drop.tip(tree_beast, matching_tips)
}
}
tree_consensus <- fix_ultrametric(tree_consensus)
ntips <- length(tree_consensus$tip.label)EN: The core diagnostic loop. It runs
bgmyc.singlephy, evaluates acceptance rates and logposterior
stationarity, plots trace graphs, and prompts you to adjust MCMC
parameters before scaling to multiple trees.
RU: Основной диагностический цикл. Запускает
bgmyc.singlephy, оценивает acceptance rates и стационарность логарифма
правдоподобия, строит графики и предлагает настроить параметры MCMC
перед многодеревным анализом.
params <- list(
mcmc = 10000, burnin = 1000, thinning = 10,
py1 = 0, py2 = 1.5, pc1 = 0, pc2 = 2,
t1 = 2, t2 = min(35, ntips - 1),
scale = c(20, 10, 5), start = c(1, 1, floor(ntips/3))
)
# EN: Diagnostic tuning loop / Цикл диагностики и настройки
repeat {
res_single <- bgmyc.singlephy(
phylo = tree_consensus, mcmc = params$mcmc, burnin = params$burnin,
thinning = params$thinning, py1 = params$py1, py2 = params$py2,
pc1 = params$pc1, pc2 = params$pc2, t1 = params$t1, t2 = params$t2,
scale = params$scale, start = params$start
)
# EN: Convergence checks / Проверка сходимости
ar <- res_single$accept
cat(sprintf("Acceptance rates: py=%.3f | pc=%.3f | th=%.3f\n", ar[1], ar[2], ar[3]))
if (requireNamespace("mcmcse", quietly = TRUE)) {
ess_vals <- sapply(1:4, function(col) round(mcmcse::ess(res_single$par[, col])))
cat(sprintf("ESS: py=%d | pc=%d | th=%d | logL=%d [Target > 200]\n",
ess_vals[1], ess_vals[2], ess_vals[3], ess_vals[4]))
}
plot(res_single)
if (!interactive() || tolower(readline("Accept parameters? / Принять параметры? (y/n): ")) != "n") break
# EN: Update parameters / Обновление параметров
params$mcmc <- input_scalar("mcmc", params$mcmc)
params$burnin <- input_scalar("burnin", params$burnin)
params$thinning <- input_scalar("thinning", params$thinning)
params$scale <- input_vector("scale", params$scale)
params$start <- input_vector("start", params$start)
}EN: Once diagnostics are stable, bgmyc.multiphylo
runs on the sampled trees.
RU: После стабилизации диагностики bgmyc.multiphylo
запускается на выбранных деревьях.
if (analysis_mode == 2) {
# EN: Parallel execution / Параллельное выполнение
n_workers <- min(parallel::detectCores(logical = FALSE) - 1, length(trees_sample))
plan(multisession, workers = max(1, n_workers))
final_res <- future_lapply(seq_along(trees_sample), function(i) {
bgmyc.singlephy(
phylo = trees_sample[[i]], mcmc = params$mcmc, burnin = params$burnin,
thinning = params$thinning, py1 = params$py1, py2 = params$py2,
pc1 = params$pc1, pc2 = params$pc2, t1 = params$t1, t2 = params$t2,
scale = params$scale, start = params$start
)
}, future.seed = TRUE)
class(final_res) <- "multibgmyc"
# EN: Gelman-Rubin R-hat / Статистика Гелмана-Рубина
if (requireNamespace("mcmcse", quietly = TRUE) && length(final_res) > 1) {
chains_list <- lapply(final_res, function(res) res$par[, 3])
names(chains_list) <- paste0("Tree_", seq_along(final_res))
rhat <- round(mcmcse::gelman(chains_list)$Rhat, 3)
cat(sprintf("Gelman-Rubin R-hat: %.3f [Target < 1.05]\n", rhat))
}
} else {
final_res <- list(res_single)
class(final_res) <- "multibgmyc"
}EN: Custom interactive visualization.
RU: Визуализация результатов.
probmat <- spec.probmat(final_res)
# EN: Synchronize tip order between tree and matrix / Синхронизация порядка таксонов
p_tree <- suppressWarnings(ggtree(tree_beast, layout = "rectangular"))
tips_data <- p_tree$data %>% filter(isTip) %>% arrange(y)
tip_order <- tips_data$label
probmat <- probmat[tip_order, tip_order]
# EN: Extract posterior probabilities for branches / Извлечение posterior для ветвей
post_col <- intersect(c("posterior", "prob", "Posterior"), colnames(p_tree$data))[1]
node_posterior <- p_tree$data[[post_col]]
names(node_posterior) <- p_tree$data$node
# EN: Custom color gradient function / Функция градиента цвета
get_pp_color <- function(pp) {
if(is.na(pp)) return("#CCCCCC")
pp <- max(0, min(1, pp))
colors <- list(c(0.0, 1.0, 0.0, 0.0), c(0.25, 1.0, 0.5, 0.0),
c(0.5, 1.0, 1.0, 0.0), c(0.75, 0.5, 1.0, 0.0), c(1.0, 0.0, 0.7, 0.0))
for(i in 1:(length(colors)-1)) {
if(pp >= colors[[i]][1] && pp <= colors[[i+1]][1]) {
t <- (pp - colors[[i]][1]) / (colors[[i+1]][1] - colors[[i]][1])
r <- colors[[i]][2] + t * (colors[[i+1]][2] - colors[[i]][2])
g <- colors[[i]][3] + t * (colors[[i+1]][3] - colors[[i]][3])
b <- colors[[i]][4] + t * (colors[[i+1]][4] - colors[[i]][4])
return(sprintf("#%02X%02X%02X", round(r*255), round(g*255), round(b*255)))
}
}
return("#CCCCCC")
}
# EN: Build Plotly Tree / Построение дерева в Plotly
edges <- p_tree$data %>% filter(!is.na(parent))
fig_tree <- plot_ly()
for(i in 1:nrow(edges)) {
child <- edges[i, ]
parent <- p_tree$data %>% filter(node == child$parent)
branch_color <- get_pp_color(node_posterior[as.character(child$node)])
fig_tree <- fig_tree %>% add_segments(
x = parent$x, xend = child$x, y = child$y, yend = child$y,
line = list(color = branch_color, width = 5), showlegend = FALSE)
fig_tree <- fig_tree %>% add_segments(
x = parent$x, xend = parent$x, y = parent$y, yend = child$y,
line = list(color = branch_color, width = 5), showlegend = FALSE)
}
# EN: Build Plotly Heatmap / Построение тепловой карты
fig_heat <- plot_ly(
z = probmat, x = 1:nrow(probmat), y = 1:ncol(probmat), type = "heatmap",
colorscale = list(list(0.0, "#F7FCF5"), list(0.5, "#41AB5D"), list(1.0, "#00441B")),
zmin = 0, zmax = 1, showscale = TRUE
)
# EN: Combine 1:1 / Объединение 1:1
fig_combined <- subplot(fig_tree, fig_heat, nrows = 1, widths = c(0.5, 0.5), shareY = TRUE) %>%
layout(yaxis = list(autorange = "reversed", showticklabels = FALSE),
xaxis = list(showticklabels = FALSE),
xaxis2 = list(showticklabels = FALSE),
yaxis2 = list(autorange = "reversed", showticklabels = FALSE))
htmlwidgets::saveWidget(fig_combined, "bGMYC_interactive_heatmap.html", selfcontained = TRUE)EN: Delimitation.
RU: Делимитация.
# EN: Export clusters at different thresholds / Экспорт кластеров на разных порогах
for (p in c(0.05, 0.01)) {
out <- bgmyc.point(probmat, ppcutoff = p)
df <- data.frame(
Sequence = unlist(out),
MOTU_bGMYC = rep(seq_along(out), lengths(out)),
stringsAsFactors = FALSE
)
write.table(df, file = sprintf("Delimitation_bGMYC_%.2f.csv", p),
row.names = FALSE, sep = ";", dec = ".", quote = FALSE, fileEncoding = "UTF-8")
}
# EN: Export full probability matrix / Экспорт полной матрицы вероятностей
spec_out <- bgmyc.spec(final_res)
write.csv(spec_out$specprobs, "bGMYC_full_probs.csv", row.names = FALSE)EN: bgmyc.multiphylo() automatically parallelizes
across physical CPU cores. To limit cores (e.g., to 6), run before
analysis: options(mc.cores = 6).
RU: bgmyc.multiphylo() автоматически использует все
физические ядра. Чтобы ограничить число ядер (например, до 6), выполните
перед запуском: options(mc.cores = 6).
—
| Parameter / Параметр | Role / Роль | Recommended Range | Biological/Statistical Notes / Примечания |
|---|---|---|---|
mcmc |
Chain length / Длина цепи | 10k (test), 50k+ (final) |
Longer chains improve posterior resolution. / Длинные цепи улучшают апостериорную оценку. |
burnin |
Warm-up / Разогрев | 20–30% of mcmc |
Discards non-stationary start. Increase if logposterior drifts. / Отбрасывает неустановившуюся фазу. |
thinning |
Sampling interval / Интервал выборки | 10–50 |
Reduces autocorrelation & RAM. Higher for long chains. / Снижает автокорреляцию и нагрузку на память. |
py1, py2 |
Yule rate prior / Априор видообразования | 0, 0.5–1.5 |
Model: λ ∝ n^py. py > 1.5
blurs Yule/Coalescent boundary. / >1.5 размывает границу модели. |
pc1, pc2 |
Coalescent prior / Априор коалесценции | 0, 1.0–2.0 |
Models Ne change. pc < 1 →
decline, pc > 1 → growth. / Моделирует динамику
эффективного размера популяции. |
t1, t2 |
Threshold prior (species count) / Априор числа видов | 2, min(35, ntips-5) |
Must be < ntips. Auto-capped to prevent
crashes. / Строго < числа таксонов. |
scale |
Proposal step widths / Ширина предложений MCMC | c(20–30, 10–15, 3–7) |
Higher = more conservative. Tune via acceptance rates. / Выше = консервативнее. Настраивается по acceptance rates. |
ppcutoff |
Lumping threshold / Порог объединения | 0.05 (variable), 0.95
(strict) |
Low = captures high intraspecific variation/ILS. / Низкий = учитывает высокую внутривидовую изменчивость. |
EN: After the diagnostic run, evaluate two
metrics:
1. Acceptance Rates: 0.20–0.40 is optimal.
<0.15 → decrease scale.
>0.50 → increase scale.
2. Trace Plots (“Fuzzy Caterpillars”): After burnin,
parameters should oscillate horizontally around a stable mean.
Upward/downward trends → increase burnin or mcmc. Sticky steps → scale
too high. Smooth/lazy curves → scale too low. Hitting bounds → widen
priors.
RU: После диагностического запуска проверьте два
показателя:
1. Acceptance Rates: Оптимум 0.20–0.40.
<0.15 → уменьшите scale.
>0.50 → увеличьте scale.
2. Графики (“пушистые гусеницы”): После burnin
параметры должны колебаться горизонтально вокруг стабильного среднего.
Тренды вверх/вниз → увеличьте burnin или mcmc.
Ступеньки → scale слишком высок. Гладкие кривые →
scale слишком низок. Прилипание к границам → расширьте
априоры.
EN: - eval = FALSE in code chunks
prevents CRAN from timing out during automated checks.
- To run interactively: change eval = FALSE to
eval = TRUE in the first chunk, or simply copy-paste chunks
into RStudio console and execute sequentially.
- Always run diagnostics on 1 tree before scaling to
multiPhylo.
RU: - eval = FALSE предотвращает
таймауты при автоматической проверке CRAN.
- Для локального запуска: измените eval = FALSE на
eval = TRUE в первом блоке, или копируйте блоки в консоль
RStudio и запускайте последовательно.
- Всегда запускайте диагностику на 1 дереве перед переходом к
multiPhylo.
References / Ссылки: Pons et al. 2006 Syst. Biol. 55:595; Reid & Carstens 2012 Mol. Ecol. Res. 12:446.
vignette("bGMYC4-interactive", package = "bGMYC4")
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.