跳转至

152_微生物组源追踪

一句话概述

微生物组源追踪(Source Tracking)利用贝叶斯模型或矩阵分解方法,从已知来源环境(sources)的微生物群落组成出发,定量估计未知样本(sink)中各来源的贡献比例,广泛应用于污染溯源、传播追踪和生态学研究。


核心知识点总览

知识点说明
源追踪概念估计sink样本中来自各source的微生物贡献比例
SourceTracker2基于Gibbs采样的贝叶斯源追踪方法
FEAST基于EM算法的快速源追踪(比SourceTracker快100倍)
Source-Sink模型Source为已知来源,Sink为待分解的目标样本
Unknown source未被已知source解释的微生物比例
OTU/ASV表输入数据:微生物分类单元的丰度矩阵
应用场景水源污染、医院感染溯源、人体微生物来源
方法对比速度、精度、对稀有taxa的敏感度差异

各步骤详解

第一步:源追踪的基本概念

白话解释: 想象你在一条河里发现了一些"可疑"的微生物。上游有一个养殖场、一个城市污水口、一片自然湿地。源追踪就是通过比较河水样本和三个上游来源的微生物"指纹",估计河水中有多少比例来自养殖场、多少来自污水、多少来自自然环境。

技术原理: 假设sink样本的微生物组成是各source的混合: $$P(sink) = \sum_{k=1}^{K} \pi_k \cdot P(source_k) + \pi_{unknown} \cdot P(unknown)$$

  • π_k:source k的贡献比例 (Σπ = 1)
  • P(source_k):source k的微生物群落分布
  • P(unknown):未知来源的均匀分布

代码概念:

import numpy as np

# 概念演示
# 3个source + 1个unknown
source_profiles = np.array([
    [0.4, 0.3, 0.2, 0.1, 0.0],  # 土壤
    [0.1, 0.1, 0.3, 0.3, 0.2],  # 污水
    [0.2, 0.4, 0.1, 0.2, 0.1],  # 肠道
])
unknown_profile = np.array([0.2, 0.2, 0.2, 0.2, 0.2])  # 均匀

# 真实混合比例
true_mix = np.array([0.3, 0.4, 0.2, 0.1])  # 土壤30%, 污水40%, 肠道20%, unknown10%

# 生成sink样本
all_profiles = np.vstack([source_profiles, [unknown_profile]])
sink_expected = true_mix @ all_profiles
print("Sink profile:", sink_expected)


第二步:SourceTracker2分析

白话解释: SourceTracker2使用贝叶斯方法,通过Gibbs采样来估计每条序列最可能来自哪个source。就像一个侦探逐条检查"证据"(每条序列),根据各source的"档案"(微生物组成)判断它最可能来自哪里。

技术原理: - 使用Dirichlet-Multinomial模型 - Gibbs采样逐个分配每条序列到source - 输出:每个sink样本中各source的比例 + 未知比例 - 支持LOO(leave-one-out)交叉验证评估准确性

代码示例:

# === 安装 ===
pip install sourcetracker

# === 输入文件准备 ===
# 1. OTU/ASV表 (BIOM格式或TSV)
# 行: 样本, 列: OTU/ASV
# 需要包含source和sink样本

# 2. Metadata文件 (mapping file)
# SampleID  SourceSink  Env
# Source1   source      Soil
# Source2   source      Soil
# Source3   source      Sewage
# Sink1     sink        River
# Sink2     sink        River

# === Python API ===
import sourcetracker
import pandas as pd
import numpy as np
from biom import load_table

# 加载数据
otu_table = pd.read_csv("otu_table.tsv", sep="\t", index_col=0)
metadata = pd.read_csv("metadata.tsv", sep="\t", index_col=0)

# 分离source和sink
source_mask = metadata["SourceSink"] == "source"
sink_mask = metadata["SourceSink"] == "sink"

source_data = otu_table.loc[source_mask]
sink_data = otu_table.loc[sink_mask]
source_envs = metadata.loc[source_mask, "Env"]

# 运行SourceTracker2
# 命令行方式(推荐):
# sourcetracker2 gibbs \
#   -i otu_table.biom \
#   -m mapping.txt \
#   --source_sink_column SourceSink \
#   --source_column_value source \
#   --sink_column_value sink \
#   --source_category_column Env \
#   -o results/ \
#   --jobs 4
# === 命令行运行 ===
sourcetracker2 gibbs \
  -i otu_table.biom \
  -m mapping.txt \
  --source_sink_column SourceSink \
  --source_column_value source \
  --sink_column_value sink \
  --source_category_column Env \
  --loo \
  -o results/ \
  --draws_per_restart 10 \
  --burnin 100 \
  --restarts 5 \
  --jobs 8

# 输出文件:
# results/
#   mixing_proportions.txt    : 各sink中source比例
#   mixing_proportions_stds.txt : 标准差
#   source_predictions/       : LOO验证结果

第三步:FEAST快速源追踪

白话解释: FEAST(Fast Expectation-mAximization for Source Tracking)比SourceTracker2快100倍以上,特别适合大数据集。它用EM算法替代了Gibbs采样,数学上等价但计算效率高得多。

技术原理: - 基于期望最大化(EM)算法 - 将source组成建模为Dirichlet-Multinomial - 通过交替更新mixing比例(E步)和source参数(M步) - 支持多个source环境的嵌套结构

代码示例:

# === 安装FEAST ===
# devtools::install_github("cozygene/FEAST")
library(FEAST)

# === 准备输入数据 ===
# OTU表: 行=样本, 列=OTU/ASV (count数据)
otu_table <- read.csv("otu_counts.csv", row.names = 1)

# Metadata
metadata <- data.frame(
  Env = c(rep("Soil", 5), rep("Sewage", 5), rep("Gut", 3), 
          rep("River", 4)),  # 环境类型
  SourceSink = c(rep("Source", 13), rep("Sink", 4)),  # source/sink标记
  id = 1:17,
  row.names = rownames(otu_table)
)

# === 运行FEAST ===
# FEAST逐个sink运行
results_list <- list()

for (i in which(metadata$SourceSink == "Sink")) {
  # 当前sink
  sink_sample <- otu_table[i, , drop = FALSE]

  # 对应的source
  source_indices <- which(metadata$SourceSink == "Source")
  source_samples <- otu_table[source_indices, ]
  source_envs <- metadata$Env[source_indices]

  # 组装FEAST输入
  combined <- rbind(sink_sample, source_samples)
  meta_feast <- data.frame(
    Env = c("Sink", source_envs),
    SourceSink = c("Sink", rep("Source", length(source_indices))),
    id = c(i, source_indices),
    row.names = rownames(combined)
  )

  # 运行
  feast_result <- FEAST(
    C = as.matrix(combined),
    metadata = meta_feast,
    different_sources_flag = 1,  # 1=不同source有不同Env
    dir_path = "feast_output/",
    outfile = paste0("sink_", i)
  )

  results_list[[rownames(otu_table)[i]]] <- feast_result
}

# === 结果整合与可视化 ===
library(ggplot2)
library(tidyr)

# 读取FEAST结果
results_df <- do.call(rbind, lapply(names(results_list), function(sink) {
  res <- results_list[[sink]]
  data.frame(Sink = sink, Source = names(res), Proportion = as.numeric(res))
}))

# 堆叠柱状图
ggplot(results_df, aes(x = Sink, y = Proportion, fill = Source)) +
  geom_bar(stat = "identity") +
  theme_minimal() +
  scale_fill_brewer(palette = "Set3") +
  labs(title = "FEAST Source Tracking Results",
       y = "Proportion", x = "Sink Sample") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))


第四步:方法对比与选择指南

对比表:

特征SourceTracker2FEAST
算法Gibbs采样(贝叶斯)EM算法
速度慢(分钟到小时)快(秒到分钟)
精度高(与ST2相当)
Unknown估计内置内置
大数据集较慢适合
不确定性估计提供后验分布/SD仅点估计
语言PythonR
稀有taxa敏感度较好中等
适用场景小数据集/需要置信区间大数据集/快速筛查

选择建议:

choose_source_tracker <- function(n_samples, need_CI, compute_time_limit) {
  if (n_samples > 500 | compute_time_limit == "minutes") {
    return("FEAST - 大数据集或需快速结果")
  }
  if (need_CI) {
    return("SourceTracker2 - 需要不确定性估计")
  }
  return("两者皆可, FEAST更快")
}


第五步:模拟数据验证与结果评估

白话解释: 源追踪结果靠不靠谱?用模拟数据验证——已知真实混合比例的情况下,看工具能不能正确还原。

代码示例:

# === 模拟混合数据 ===
simulate_mixed_community <- function(source_profiles, mixing_props, n_reads = 10000) {
  # source_profiles: K个source的相对丰度矩阵(K × P)
  # mixing_props: 混合比例向量(长度K+1, 最后一个是unknown)

  K <- nrow(source_profiles)
  P <- ncol(source_profiles)

  # 各source贡献的reads数
  n_from_source <- round(mixing_props[1:K] * n_reads)
  n_unknown <- n_reads - sum(n_from_source)

  # 从各source抽样
  sink_counts <- rep(0, P)
  for (k in 1:K) {
    if (n_from_source[k] > 0) {
      sink_counts <- sink_counts + rmultinom(1, n_from_source[k], source_profiles[k,])
    }
  }
  # Unknown (均匀分布)
  if (n_unknown > 0) {
    sink_counts <- sink_counts + rmultinom(1, n_unknown, rep(1/P, P))
  }

  return(as.vector(sink_counts))
}

# 创建模拟数据
set.seed(42)
n_taxa <- 200
n_sources <- 3
source_profiles <- matrix(rgamma(n_sources * n_taxa, shape = 0.5), 
                          nrow = n_sources, ncol = n_taxa)
source_profiles <- source_profiles / rowSums(source_profiles)

# 模拟多个sink
true_props <- matrix(c(
  0.5, 0.3, 0.1, 0.1,
  0.1, 0.6, 0.2, 0.1,
  0.3, 0.3, 0.3, 0.1
), nrow = 3, byrow = TRUE)

simulated_sinks <- t(apply(true_props, 1, function(p) {
  simulate_mixed_community(source_profiles, p, n_reads = 50000)
}))

# 运行源追踪并与真实比例比较
# ... (运行FEAST/SourceTracker2)
# 评估指标: MAE, RMSE, Pearson相关


第六步:实际案例——水环境污染溯源

代码示例:

library(FEAST)
library(ggplot2)
library(ggalluvial)

# === 水环境源追踪案例 ===
# Source类别: 
#   - 人粪便(Human fecal)
#   - 动物粪便(Animal fecal: 牛/鸡/猪)
#   - 土壤(Soil)
#   - 污水处理厂出水(WWTP effluent)
# Sink: 下游河水样本

# 结果可视化 - 冲积图(Alluvial plot)
results_long <- data.frame(
  Sink = rep(c("Site_A", "Site_B", "Site_C", "Site_D"), each = 5),
  Source = rep(c("Human", "Cattle", "Poultry", "Soil", "Unknown"), 4),
  Proportion = c(
    0.35, 0.15, 0.05, 0.25, 0.20,  # Site A
    0.45, 0.10, 0.08, 0.15, 0.22,  # Site B
    0.20, 0.30, 0.15, 0.20, 0.15,  # Site C
    0.10, 0.05, 0.03, 0.45, 0.37   # Site D
  )
)

# 堆叠柱状图
ggplot(results_long, aes(x = Sink, y = Proportion, fill = Source)) +
  geom_bar(stat = "identity", width = 0.7) +
  scale_fill_manual(values = c("Human" = "#E41A1C", "Cattle" = "#377EB8",
                                "Poultry" = "#4DAF4A", "Soil" = "#984EA3",
                                "Unknown" = "grey70")) +
  theme_minimal() +
  labs(title = "Microbial Source Tracking - River Sites",
       y = "Source Proportion", x = "Sampling Site") +
  theme(legend.position = "right")


实战命令

# === 环境安装 ===
# SourceTracker2
pip install sourcetracker

# FEAST (R)
Rscript -e 'devtools::install_github("cozygene/FEAST")'

# === SourceTracker2 完整运行 ===
sourcetracker2 gibbs \
  -i feature_table.biom \
  -m sample_metadata.txt \
  --source_sink_column SourceSink \
  --source_column_value source \
  --sink_column_value sink \
  --source_category_column Env \
  --loo \
  --draws_per_restart 10 \
  --burnin 100 \
  --restarts 5 \
  --jobs 16 \
  -o sourcetracker_results/

# === QIIME2集成 (如果在QIIME2生态中) ===
qiime sourcetracker2 gibbs \
  --i-feature-table table.qza \
  --m-sample-metadata-file metadata.tsv \
  --p-source-sink-column SourceSink \
  --p-source-column-value source \
  --p-sink-column-value sink \
  --p-source-category-column Env \
  --o-mixing-proportions proportions.qza

面试常问点

Q1:微生物组源追踪的基本原理是什么?

A: 源追踪假设sink样本(未知来源)的微生物群落是多个已知source群落的混合。通过概率模型(如Dirichlet-Multinomial)估计各source对sink的贡献比例。核心是将sink中每个taxa的丰度分解为各source贡献的加权和,加上一个"unknown"成分代表未被已知source解释的部分。

Q2:SourceTracker2和FEAST的算法区别是什么?

A: SourceTracker2使用Gibbs采样(MCMC方法)逐个将序列分配到source,可以获得后验分布和不确定性估计,但计算慢。FEAST使用EM算法迭代优化mixing比例和source参数,收敛快(通常几十次迭代),速度比SourceTracker2快约100倍,但只输出点估计。两者精度相当。

Q3:"Unknown"比例该如何解读?

A: Unknown代表sink中无法被任何已知source解释的微生物比例。高Unknown可能说明:(1) 存在未采样的source环境;(2) source采样不够充分(样本量少);(3) sink中有独特的环境特异性微生物。实践中,Unknown > 30%可能提示需要补充更多source类型或增加source样本量。

Q4:源追踪对输入数据有什么要求?

A: (1) Source样本数量:每个source类别建议至少5-10个代表性样本(越多越稳定);(2) 测序深度:建议rarefaction到合理深度(如10,000 reads/sample),确保source和sink深度一致;(3) 分类分辨率:通常使用genus或ASV级别;(4) Source覆盖度:应尽量覆盖sink中可能的所有来源。

Q5:源追踪在公共卫生中有哪些应用?

A: (1) 水体粪便污染溯源(人粪vs动物粪vs污水处理厂);(2) 医院感染传播链追踪(患者→环境→患者);(3) 食品安全中的污染来源鉴定;(4) 新生儿肠道菌群来源分析(母体阴道/皮肤/口腔/环境);(5) 室内微生物组来源(人体/室外/建筑材料)。


易错点

1. Source样本代表性不足

错误: 每个source类别只有1-2个样本。 正确做法: 每个source至少5-10个样本以捕获组内变异性。Source样本量不足会导致source profile估计不准确,下游所有比例都不可靠。

2. 未做rarefaction或深度归一化

错误: Source测序深度50000, Sink深度5000,直接分析。 正确做法: 先rarefaction到相同深度,或使用相对丰度。深度差异会系统性偏倚结果。

3. 遗漏重要source

错误: 水体源追踪只考虑人粪和动物粪,忽略了土壤和植物来源。 正确做法: 尽可能覆盖所有潜在source。遗漏的source的贡献会被错误分配给已有source或inflating unknown。

4. 对同一环境的不同批次未考虑时间变异

错误: 用夏季采集的source数据去追踪冬季的sink。 正确做法: 微生物群落有季节性变化。Source采样应尽可能与sink时间匹配,或多季节采样覆盖时间变异。

5. 将比例当作绝对丰度

错误: "Site A有35%来自人粪便"解读为"Site A有大量人粪便微生物"。 正确做法: 比例反映的是群落组成的来源,而非绝对生物量。高比例可能只是因为其他source贡献极低。需要结合指示微生物(如HF183)的qPCR来验证绝对量。


补充知识

其他源追踪工具

  • mSourceTracker: 基于机器学习的源追踪(SVM/RF)
  • BayesianSourceTracking: R包,贝叶斯非参数方法
  • STENSL: 基于稀疏tensor的源追踪
  • 指示微生物qPCR: 非测序方法,如HF183(人特异性)、Rum2Bac(反刍动物)

实验设计建议

  • Source样本:每个环境类别10+个样本
  • Sink样本:根据研究问题设计采样点
  • 测序深度:至少10,000-20,000 reads/sample
  • 分类数据库:SILVA/Greengenes2, 保持一致性
  • 阴性对照:含空白提取和测序对照,排除污染

与其他微生物组分析的整合

  • 源追踪 → 差异丰度分析:鉴定各source特异性指示taxa
  • 源追踪 → 网络分析:不同source微生物的互作模式
  • 源追踪 → 功能预测:各source贡献的功能潜力差异