Files
2026-08-03 18:42:47 +08:00

177 lines
5.0 KiB
R
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env Rscript
## ===================== 1. 解析命令行参数 =====================
args <- commandArgs(trailingOnly = TRUE)
if (length(args) < 2) {
stop("用法: Rscript tree_plot.R <treefile> <subfamily_file> [output_pdf] [x_max]\n",
call. = FALSE)
}
treefile <- args[1]
subfamily_file <- args[2]
## 第三个参数:输出 pdf 名称(可选)
if (length(args) >= 3) {
output_pdf <- args[3]
} else {
## 如果没给,就用树文件名去掉后缀自动生成
output_pdf <- sub("\\.[^.]*$", "", treefile)
output_pdf <- paste0(output_pdf, ".pdf")
}
## 第四个参数:x 轴最大值(可选)
if (length(args) >= 4) {
x_max <- as.numeric(args[4])
} else {
x_max <- 18
}
cat("树文件: ", treefile, "\n")
cat("亚家族文件: ", subfamily_file, "\n")
cat("输出文件: ", output_pdf, "\n")
cat("x_max: ", x_max, "\n")
## ===================== 2. 加载所需 R 包 =====================
suppressPackageStartupMessages({
library(ape)
library(ggtree)
library(tidytree)
library(dplyr)
library(RColorBrewer)
library(ggplot2)
})
## ===================== 3. 封装绘图函数 =====================
plot_iqtree_by_subfamily <- function(treefile, subfamily_file, x_max = 18) {
## ---------- 3.1 读树 ----------
tree <- read.tree(treefile)
## 转成 tibble(tidytree::as_tibble)
tree_df <- as_tibble(tree)
## 手动添加 isTip 列:phylo 对象中,1:Ntip 是叶节点
tree_df$isTip <- tree_df$node <= length(tree$tip.label)
## ---------- 3.2 读亚家族文件 ----------
## 格式: 两列,无表头:geneID subfamily
subfam <- read.table(subfamily_file,
header = FALSE,
stringsAsFactors = FALSE)
colnames(subfam) <- c("label", "subfamily") # label 要与树的 tip.label 对应
## ---------- 3.3 生成 support 列 ----------
## 只给内部节点算 bootstrap,tip 为 NA
tree_df$support <- ifelse(
tree_df$isTip,
NA_real_,
suppressWarnings(as.numeric(tree_df$label))
)
## ---------- 3.4 合并 subfamily 信息到 tree_df ----------
tree_df <- dplyr::left_join(tree_df, subfam, by = "label")
## ---------- 3.5 自动配色(按 subfamily) ----------
subfam_levels <- sort(unique(subfam$subfamily))
n_subfam <- length(subfam_levels)
if (n_subfam == 0) {
stop("在亚家族文件中没有检测到任何 subfamily,请检查文件格式。", call. = FALSE)
}
## Set1 最多 9 个颜色;至少 3 个颜色
n_col <- max(3, min(n_subfam, 9))
base_cols <- RColorBrewer::brewer.pal(n_col, "Set1")
subfam_cols <- setNames(base_cols[seq_len(n_subfam)], subfam_levels)
## ---------- 3.6 计算每个 subfamily 的 clade 根节点 node ----------
## 使用 getMRCA,若某 subfamily 只有 1 条基因,则用它自己的 tip 节点
node_subfam <- subfam %>%
dplyr::group_by(subfamily) %>%
dplyr::summarise(
node = {
tips <- label
if (length(tips) == 1) {
which(tree$tip.label == tips)
} else {
getMRCA(tree, tips)
}
},
.groups = "drop"
)
## ---------- 3.7 构建 ggtree 图 ----------
p <- ggtree(tree, branch.length = "none") %<+% tree_df +
## 节点 bootstrap 支持度
geom_nodepoint(
aes(fill = cut(support, c(0, 50, 75, 100))),
shape = 21,
size = 2,
na.rm = TRUE
) +
scale_fill_manual(
values = c("black", "grey", "white"),
guide = "legend",
name = "Bootstrap Percentage (BP)",
breaks = c("(75,100]", "(50,75]", "(0,50]"),
labels = expression(BP > 75,
50 < BP * "<=75",
BP <= 50)
) +
## tip 按亚家族上色
geom_tippoint(
aes(color = subfamily),
size = 2,
na.rm = TRUE
) +
scale_color_manual(
values = subfam_cols,
name = "Subfamily"
) +
## 叶子标签(基因 ID)
geom_tiplab(offset = 0.5, size = 3) +
## 标题 & x 轴范围
ggtitle("Phylogenetic Tree") +
xlim(NA, x_max) +
theme_tree() +
theme(
plot.title = element_text(hjust = 0.5),
legend.background = element_rect(color = "#969696",
fill = "#d9d9d9")
)
## ---------- 3.8 给每个 subfamily 添加 clade 标签 ----------
for (i in seq_len(nrow(node_subfam))) {
this_sub <- node_subfam$subfamily[i]
this_node <- node_subfam$node[i]
this_col <- subfam_cols[[this_sub]]
p <- p +
geom_cladelab(
node = this_node,
label = this_sub,
align = TRUE,
angle = 270,
offset = 6.5,
offset.text = 1,
textcolor = this_col,
barcolor = this_col,
barsize = 1.5,
extend = 0.7
)
}
return(p)
}
## ===================== 4. 调用函数并保存图像 =====================
p <- plot_iqtree_by_subfamily(treefile, subfamily_file, x_max = x_max)
ggsave(output_pdf, p, width = 8, height = 10)
cat("已输出图像到: ", output_pdf, "\n")