165_微生物组数据模拟¶
一句话概述¶
微生物组数据模拟使用SparseDOSSA2(基于参数统计模型)、CAMISIM(基于基因组的宏基因组reads模拟)和InSilicoSeq(通用测序模拟器)等工具生成具有已知ground truth的合成微生物组数据,用于方法基准测试、统计力分析和工具开发验证。
核心知识点总览¶
| 知识点 | 说明 |
|---|---|
| SparseDOSSA2 | 基于学习参数的稀疏组成性数据模拟器 |
| CAMISIM | 从参考基因组模拟宏基因组reads |
| InSilicoSeq | 基于错误模型的通用测序reads模拟 |
| 用途 | 方法基准测试、统计力计算、流程验证 |
| 稀疏性模拟 | 模拟真实微生物组数据的高零值比例 |
| 差异丰度模拟 | 模拟组间差异用于评估DA方法 |
| reads模拟 | 从基因组生成带真实错误率的fastq文件 |
| 组成效应 | 模拟总丰度变化导致的组成效应 |
各步骤详解¶
第一步:为什么需要模拟数据¶
白话解释: 评估分析方法好不好需要"标准答案"——真实数据没有标准答案(你不知道哪些菌真的差异)。模拟数据的好处是你知道"真相"(ground truth)——你设计了哪些菌有差异、差异多大——然后看分析工具能不能正确找到它们。这就像考试出题——出题的人知道答案,才能评判学生做得对不对。
三种模拟层次: | 层次 | 工具 | 输出 | 用途 | |------|------|------|------| | 丰度表模拟 | SparseDOSSA2 | OTU/ASV counts表 | DA方法、归一化方法评估 | | 基因组reads模拟 | CAMISIM | FASTQ文件 | 全流程评估(组装/分箱/分类) | | 通用reads模拟 | InSilicoSeq | FASTQ文件 | 简单场景的reads生成 |
第二步:SparseDOSSA2 — 统计模型模拟¶
代码示例:
# 安装
# BiocManager::install("biobakery/SparseDOSSA2")
library(SparseDOSSA2)
# === 基本模拟: 从模板数据学习参数 ===
# 使用内置的HMP数据学习参数并生成模拟数据
sim_result <- SparseDOSSA2(
template = "Stool", # 使用内置stool模板
n_sample = 100, # 样本数
n_feature = 200, # 特征(taxa)数
new_features = TRUE, # 生成新特征名
verbose = TRUE
)
# 输出: 模拟的counts矩阵
simulated_counts <- sim_result$simulated_data
dim(simulated_counts) # 200 taxa × 100 samples
# === 模拟差异丰度 ===
# 设置spike-in: 特定taxa在某组中有差异
spike_metadata <- data.frame(
metadata_datum = c(rep("CaseGroup", 50), rep("ControlGroup", 50))
)
# 定义spike-in参数
spike_params <- data.frame(
feature_spiked = paste0("Feature_", 1:10), # 10个差异taxa
associated_property = rep("metadata_datum", 10),
effect_size = c(rep(2, 5), rep(-2, 5)) # 5个上调, 5个下调(log2 fold change)
)
sim_with_da <- SparseDOSSA2(
template = "Stool",
n_sample = 100,
n_feature = 200,
spike_metadata = spike_metadata,
spike_in = spike_params,
verbose = TRUE
)
# 验证: 对模拟数据运行DA方法
# ground truth: Feature_1到Feature_10是真差异
library(Maaslin2)
fit <- Maaslin2(
input_data = as.data.frame(t(sim_with_da$simulated_data)),
input_metadata = spike_metadata,
output = "maaslin2_sim/",
normalization = "TSS",
transform = "LOG"
)
# 计算性能指标
true_positives <- sum(fit$results$feature[fit$results$qval < 0.05] %in%
paste0("Feature_", 1:10))
false_positives <- sum(!fit$results$feature[fit$results$qval < 0.05] %in%
paste0("Feature_", 1:10))
precision <- true_positives / (true_positives + false_positives)
recall <- true_positives / 10
cat(sprintf("Precision: %.2f, Recall: %.2f, F1: %.2f\n",
precision, recall, 2*precision*recall/(precision+recall)))
# === 自定义模板(从自己的数据学习) ===
# 从真实数据学习参数
my_template <- fit_SparseDOSSA2(
data = real_microbiome_data, # 真实counts矩阵
control = list(verbose = TRUE)
)
# 用学习的参数模拟
sim_custom <- SparseDOSSA2(
template = my_template,
n_sample = 200
)
第三步:CAMISIM — 宏基因组reads模拟¶
代码示例:
# === 安装CAMISIM ===
git clone https://github.com/CAMI-challenge/CAMISIM.git
pip install -r CAMISIM/requirements.txt
# === 配置文件 (ini格式) ===
cat > config.ini << 'EOF'
[Main]
seed=42
phase=0 # 0=community design+read generation
max_processors=16
dataset_id=simulated_metagenome
output_directory=camisim_output/
temp_directory=/tmp/camisim/
[ReadSimulator]
readsim=art # art_illumina模拟器
error_profiles=HiSeq2500 # 错误模型
type=art
fragments_size_mean=270 # 片段大小
fragments_size_standard_deviation=27
[CommunityDesign]
ncbi_taxdump=/path/to/taxdump/
strain_simulation_template=auto
number_of_samples=10 # 样本数
[community0]
metadata=/path/to/metadata.tsv
id_to_genome_file=/path/to/id_to_genome.tsv
genomes_total=50 # 物种数
num_real_genomes=50
max_strains_per_otu=1
ratio=1 # 该community的reads比例
mode=differential # 差异模式
log_mu=1
log_sigma=2
gauss_mu=1
gauss_sigma=1
view=False
EOF
# === 准备基因组列表 ===
# id_to_genome.tsv: genome_ID \t /path/to/genome.fasta
# metadata.tsv: genome_ID \t OTU \t novelty_category
# === 运行CAMISIM ===
python CAMISIM/metagenomesimulation.py config.ini
# === 输出 ===
# camisim_output/
# *.fq.gz : 模拟的reads
# *.profile : 真实组成(gold standard)
# *.bam : reads的来源基因组标注
第四步:InSilicoSeq — 简易reads模拟¶
代码示例:
# === 安装 ===
pip install InSilicoSeq
# === 基本用法: 从多个基因组模拟宏基因组 ===
# 准备基因组文件和丰度文件
cat > abundance.txt << 'EOF'
genome1.fasta 0.30
genome2.fasta 0.25
genome3.fasta 0.20
genome4.fasta 0.15
genome5.fasta 0.10
EOF
# 模拟Illumina reads
iss generate \
--genomes genomes/*.fasta \
--abundance_file abundance.txt \
--model HiSeq \
--output sim_reads \
--n_reads 10000000 \
--cpus 16
# 输出: sim_reads_R1.fastq, sim_reads_R2.fastq
# === 不同错误模型 ===
# 可用模型: HiSeq, MiSeq, NovaSeq, basic
iss generate --genomes genomes/ --model MiSeq --n_reads 5000000 --output miseq_sim
# === 多样本不同丰度 ===
for i in $(seq 1 10); do
# 生成随机丰度(Dirichlet分布)
python -c "
import numpy as np
np.random.seed($i)
fracs = np.random.dirichlet([2]*5)
for g, f in zip(['g1','g2','g3','g4','g5'], fracs):
print(f'{g}.fasta\t{f:.4f}')
" > abundance_sample${i}.txt
iss generate \
--genomes genomes/*.fasta \
--abundance_file abundance_sample${i}.txt \
--model HiSeq \
--output sample_${i} \
--n_reads 5000000
done
第五步:模拟数据用于方法基准测试¶
代码示例:
# === 系统性基准测试框架 ===
import numpy as np
import pandas as pd
from itertools import product
# 定义模拟参数空间
param_grid = {
'n_samples': [20, 50, 100, 200],
'effect_size': [0.5, 1.0, 2.0, 3.0],
'n_features': [100, 500, 1000],
'sparsity': [0.5, 0.7, 0.9],
'n_diff_features': [5, 10, 20]
}
# 为每个参数组合生成模拟数据并测试DA方法
results = []
for params in product(*param_grid.values()):
n_samples, effect_size, n_features, sparsity, n_diff = params
# 生成模拟数据 (简化版)
# ... SparseDOSSA2或自定义模拟 ...
# 运行各DA方法
methods = ['DESeq2', 'ALDEx2', 'ANCOM-BC', 'Maaslin2', 'LinDA']
for method in methods:
# ... 运行方法 ...
# 计算性能
tp, fp, fn = calculate_confusion(detected, true_diff)
results.append({
'n_samples': n_samples,
'effect_size': effect_size,
'method': method,
'precision': tp/(tp+fp) if (tp+fp)>0 else 0,
'recall': tp/(tp+fn) if (tp+fn)>0 else 0,
'FDR': fp/(tp+fp) if (tp+fp)>0 else 0
})
results_df = pd.DataFrame(results)
# 可视化: 各方法在不同条件下的表现
import seaborn as sns
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
sns.lineplot(data=results_df, x='n_samples', y='recall', hue='method', ax=axes[0])
axes[0].set_title('Statistical Power vs Sample Size')
sns.lineplot(data=results_df, x='effect_size', y='FDR', hue='method', ax=axes[1])
axes[1].set_title('FDR Control vs Effect Size')
plt.tight_layout()
plt.savefig('benchmark_results.png', dpi=150)
实战命令¶
# === SparseDOSSA2 (R) ===
Rscript -e '
library(SparseDOSSA2)
sim <- SparseDOSSA2(template="Stool", n_sample=100, n_feature=200)
write.csv(sim$simulated_data, "simulated_counts.csv")
'
# === CAMISIM ===
python CAMISIM/metagenomesimulation.py config.ini
# === InSilicoSeq ===
iss generate --genomes genomes/ --abundance_file abundance.txt \
--model HiSeq --output sim --n_reads 10000000 --cpus 16
# === 批量模拟和基准测试 ===
python benchmark_pipeline.py --n_simulations 100 \
--methods DESeq2,ALDEx2,ANCOMBC,Maaslin2 \
--output benchmark_results/
面试常问点¶
Q1:为什么需要模拟微生物组数据?¶
A: (1) 方法基准测试:真实数据没有ground truth,无法知道哪些结果正确;(2) 统计力分析:估计发现真实差异需要的最小样本量;(3) 工具开发:在已知答案的数据上调试算法;(4) 实验设计:模拟不同效应量和样本量下的预期结果;(5) 教学:展示方法原理和局限性。
Q2:SparseDOSSA2模拟的核心模型是什么?¶
A: SparseDOSSA2使用"spike-and-slab"模型:先拟合零膨胀对数正态分布(ZILN)来模拟微生物丰度的稀疏性和组成性。从真实数据(如HMP)学习三组参数:(1) 非零概率(prevalence);(2) 非零时的均值和方差(log-normal部分);(3) 特征间的相关结构。然后通过spike-in机制在指定taxa上施加差异效应来模拟差异丰度。
Q3:CAMISIM和InSilicoSeq的区别是什么?¶
A: CAMISIM:全面的宏基因组模拟器,从完整参考基因组出发,支持群落设计、进化距离、strain-level变异、多样本差异、gold standard taxonomy标注。适合评估完整宏基因组流程(QC→组装→分箱→分类)。InSilicoSeq:更简单轻量,只做reads生成(从基因组+丰度+错误模型产生fastq)。适合快速生成测试数据或简单场景。
Q4:模拟数据与真实数据相比有哪些局限?¶
A: (1) 简化了真实的生物学复杂性(如菌种间互作、代谢依赖);(2) 统计模型可能无法完美捕捉真实数据分布的所有特征(如极端值、批次效应);(3) 已知的技术偏差(PCR偏差、DNA提取效率差异)可能未被充分模拟;(4) 时间动态和空间结构通常被忽略。建议:模拟数据用于初步筛选,最终需在真实数据上验证。
Q5:如何设计一个公平的DA方法基准测试?¶
A: (1) 多维度参数扫描:样本量、效应量、稀疏度、差异特征数;(2) 使用从真实数据学习的参数(SparseDOSSA2 custom template);(3) 多次重复(每个条件100+次模拟)减少随机波动;(4) 评估多个指标:FDR控制(是否保持5%)、Power(recall)、运行时间;(5) 包含阴性对照(零效应)检测FDR膨胀;(6) 公开代码和数据确保可重复。
易错点¶
1. 模拟参数不现实¶
错误: 所有taxa均匀分布、无稀疏性。 正确做法: 从真实数据学习参数(SparseDOSSA2的template功能)。微生物组的关键特性是高稀疏性(50-90%零值)和幂律分布。
2. 忽略组成效应¶
错误: 模拟时只改变目标taxa的绝对丰度,不考虑其他taxa的相对变化。 正确做法: 微生物组是组成性数据——一个taxa的增加会导致其他taxa的相对丰度"被动"降低。模拟应保持总reads数恒定(sum-to-1约束)。
3. 评估指标单一¶
错误: 只报告AUC不看FDR。 正确做法: 完整评估需要:(1) FDR是否被正确控制在标称水平;(2) Power/Recall;(3) Precision;(4) 排名能力(partial AUC)。特别注意FDR控制——很多方法声称高power但实际FDR远超5%。
4. 基准测试过拟合到模拟数据¶
错误: 调参使方法在自己的模拟数据上表现好。 正确做法: 使用第三方工具(如SparseDOSSA2)生成数据,而非用自己方法假设的模型生成——否则是循环论证。
补充知识¶
模拟工具扩展¶
- MetaSim: 经典宏基因组reads模拟器
- CAMI challenge: 宏基因组方法评估竞赛
- microbiomeDASim: 针对DA方法的R模拟包
- SimSeq: 基于真实数据的RNA-seq模拟(可适配)
- ART: 通用Illumina/454/Ion reads模拟器
推荐基准测试实践¶
- 报告完整的参数设置和代码
- 包含多种真实性水平的模拟
- 在真实数据上做concordance验证
- 发表数据和代码供复现