ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

微生物组分析流程实战:从FASTQ到属级注释可视化

微生物组分析流程实战:从FASTQ到属级注释可视化 做微生物组分析这几年我一直觉得“流程定不下来”是比“数据质量差”更让人头疼的事。前段时间整理了一套面向属级genus分类鉴定的综合流程从原始测序数据一路处理到物种注释、丰度统计、差异筛选和可视化跑通之后整个分析周期从以前的两三周压缩到了三四天。这套流程不算惊艳但胜在每一步都踩过坑、填过坑写出来给同行做个参考。先说清楚这套流程能解决什么问题输入是扩增子测序的双端FASTQ文件经过质控、拼接、去噪或聚类最终得到以“属”为单位分类学注释结果并输出标准化丰度表、多样性指数和一组可发布级的图表。适合16S rRNA、ITS这类扩增子数据的常规批量分析也适合需要频繁跑批次实验、想统一分析口径的课题组或检测团队。如果你还在用Excel手工整理OTU表、或者被各种软件参数搞得头大这套流程可以作为起点。1 流程整体设计与思路拆解1.1 为什么非要固定一套“综合流程”做了几年微生物组分析我最大的感受是分析流程不统一结果根本没法比。同一个数据集换个质控参数、换一个聚类算法、换一个注释数据库可能属级结论都会变——尤其是相对丰度不高的那些属稍微被“洗”一下就从表格里消失了。所以这套综合流程在设计时就定了一个原则所有关键环节的参数和算法版本尽量固定可调节的部分集中写进一个配置文件任何一次分析都能回溯到具体的软件版本、数据库版本和参数组合。这样无论是一个月后还是半年后重新跑同一批数据结果依旧可复现审稿人问起来也拿得出完整记录。1.2 流程选型背后的关键判断流程的骨干我选了QIIME2和R语言生态的组合。QIIME2负责从原始数据到特征表、再到分类学注释的整个上游过程R语言负责下游的统计分析、可视化和个性化图表输出。两套生态各有优势组合起来比较顺手。为什么用QIIME2而不是纯用usearch或者vsearch的脚本一是QIIME2的插件机制把每个步骤的数据追踪做得很清楚每一步的输入输出都有明确的类型定义不容易出现“中间文件搞混了”这种低级错误二是有可视化工具q2-view质控曲线、alpha稀疏曲线、分类学柱状图都能直接用浏览器预览对于需要反复试参数的场景非常方便。不过QIIME2也有让人恼火的地方环境管理复杂偶尔会出版本兼容问题。我的处理方式是用Conda环境的YAML文件把整个环境锁死新建机器也能一键恢复这套流程的配置文件里我也附了环境导出文件照跑就行。1.3 流程的整体架构这条流程大致分为四个阶段数据预处理、特征表构建、分类注释、下游统计与可视化。下面这张简表是每个阶段的核心任务和主要工具后面几节我会逐个环节拆细节阶段核心任务主要工具数据预处理质控、去噪、拼接双端序列fastp / cutadapt、DADA2特征表构建生成ASV表或OTU表过滤低丰度特征DADA2 / vsearch分类学注释属级分类注释统一数据库与置信度QIIME2 feature-classifier下游统计与可视化多样性分析、物种差异与图表输出R语言tidyverse、phyloseq说句实在话流程本身并不新鲜新鲜的是把每一步需要注意的坑都提前踩掉、把参数定成一个相对通用的默认值。接下来逐个环节展开讲。2 数据预处理决定后续一切的核心环节2.1 质控参数怎么调才能不冤枉数据扩增子数据的质控很多人一上来就按默认值跑结果要么太严把大量有效序列滤掉要么太松把低质量序列带进下游。我调试这套流程时尝试过fastp和Trimmomatic两种方案最终用的是fastp。fastp的优势是快而且会把每条序列的质量分布、碱基含量、接头残留情况自动统计成一份网页报告。扩增子数据里引物序列通常在测序读段的两端所以质控时除了质量值过滤还一定要做引物切除。这一步没做干净后面注释出来的结果会混入大量非目标区段序列。我的做法是先用cutadapt切引物再用fastp做质量过滤。至于质量阈值一般建议Q20以下直接裁掉滑窗大小设为4bp平均质量低于Q25的读段丢弃。这套参数在我们试过的土壤、肠道、水体样本上表现都算稳定实测下来很少误杀有效序列。2.2 双端拼接与嵌合体过滤的取舍切完引物和低质量序列之后下一步是双端拼接。对于MiSeq和NovaSeq平台常见的2×250或2×300测序插入片段长度控制在350-450bp左右时双端读段的重叠区足够长拼接成功率很高。拼接的具体参数主要看最小重叠长度。默认设为12bp太容易产生错配拼接我一般设到20-30bp再设置错配率不超过0.1。如果样本本身多样性很高比如复杂土壤样品建议把重叠长度要求提高一点减少嵌合体拼接。嵌合体过滤是很多初学者容易忽略的步骤。嵌合体会把两段不同物种的序列拼接在一起导致注释结果出现“不存在的属”。DADA2的removeBimeraDenovo方法是目前的主流选择按一致序列做嵌合体筛选速度可以接受效果也比较稳定。跑完之后一定要看一眼过滤率如果超过20%大概率是前面质控步骤出了问题。2.3 选ASV还是OTU我的建议现在主流是ASVAmplicon Sequence Variant也就是用DADA2等工具去噪把单碱基差别的序列区分开。相比传统的OTU聚类如97%相似度ASV不依赖聚类阈值不同研究之间的可比较性更好——这是当年我们选择ASV路线的核心原因。用DADA2要留意两个点一是它的dada算法对测序错误率模型比较敏感跑之前最好用learnErrors学一下当前批次数据的错误率不要硬套默认模型二是它的运行速度不算快样本量特别大的时候建议切片并行每个样本单独跑denoise步骤再合并。如果你偏保守或者后续需要和大量历史OTU数据对比可以保留vsearch的OTU聚类分支。我在流程里也在配置文件中留有开关两种模式都能跑只是默认走ASV。3 属级分类注释流程的核心命门3.1 参考数据库的选择与格式化属级注释的结果质量七成取决于参考数据库。常用的三套库分别是Greengenes2、SILVA和GTDB。Greengenes在16S领域用得很广但是更新速度一般SILVA的注释覆盖度和更新频率都不错GTDB则是目前系统发育信息最全的框架但它的属名和传统分类体系差异比较大接轨时需要注意。如果目标是和文献中常见结果作对比我建议用SILVA作为主力库。ITS数据则用UNITE这一点没什么争议。选好数据库之后别忘了做一件重要的事将数据库序列和分类学信息整理成QIIME2可以识别的格式然后用q2-feature-classifier训练分类器。3.2 训练自己的分类器不要图省事用现成的我知道很多人习惯直接下载那些现成的分类器文件但我的经验是不同引物区域训练出来的分类器差异很大直接用通用分类器注释自己的V3-V4区数据效果往往不如针对自己引物训练的。所以流程中专门加了一步“训练分类器”。分类器训练的基本命令分为两步第一步提取目标区域的序列第二步用这些序列训练Naive Bayes分类器qiime feature-classifier extract-reads \ --i-sequences silva-138-99-seqs.qza \ --p-f-primer CCTACGGGNGGCWGCAG \ --p-r-primer GACTACHVGGGTATCTAATCC \ --o-reads ref-seqs-v3-v4.qza qiime feature-classifier fit-classifier-naive-bayes \ --i-reference-reads ref-seqs-v3-v4.qza \ --i-reference-taxonomy silva-138-99-tax.qza \ --o-classifier silva-v3-v4-classifier.qza注意其中引物序列的位置需要和你的扩增引物保持完全一致否则提取出来的参考序列区域会对不上分类器性能会直线下降。训练完成后对每个样本做注释qiime feature-classifier classify-sklearn \ --i-classifier silva-v3-v4-classifier.qza \ --i-reads rep-seqs.qza \ --o-classification taxonomy.qza整个过程大概会花十几分钟到几个小时不等取库近缘种的覆盖度越高注释速度越慢但准确率也越高。3.3 置信度阈值怎么设才合理classify-sklearn默认的置信度阈值是0.7意思是分类器认为某个序列归属于某个分类单元的概率超过70%才给出注释。这个值并不是越高越好——设太高会制造大量“Unassigned”设太低又会把错误的属名标上去。实际操作中我一般建议不同层级区别对待界门纲目水平用0.8科水平用0.7属水平用0.5-0.6。目前QIIME2的classify-sklearn只能配置一个全局阈值所以我通常备份一个分类器分两次注释第一次注释全库数据用0.7阈值保证整体准确率对重点关注的“目标属”单独再做一次低阈值匹配再用BLAST或VSEARCH做二次验证。如果结果中出现了大片“g__”或“s__”尤其在高丰度物种里不要急着降阈值。先检查参考数据库是否覆盖你的样本类型。比如做海洋样本时很多近海特有属在SILVA里注释就很弱这时候更建议找针对性的数据库而不是一味调低阈值。4 流程编排与自动化从“能跑”到“能复用”4.1 Snakemake脚本的骨架设计当我需要反复跑几十个样本、几批不同数据时光靠一条条敲命令已经不行了必须把流程写成可自动执行的形式。我选择的是Snakemake理由很直白语法直观弱依赖Python扩展性好还能天然实现断点续跑和并行。整个流程的Snakefile逻辑可以理解成“目标文件驱动”写清楚每个中间文件怎么生成Snakemake会根据文件的依赖关系自动判断哪些步骤需要重新运行不会重复计算已经完成的任务。核心骨架大致是这样rule all: input: results/taxonomy.qza, results/core-metrics/faith_pd_vector.qza, results/barplots.qzv rule import_data: input: data/manifest.tsv output: results/imported.qza conda: envs/qiime2.yaml shell: qiime tools import --type SampleData[PairedEndSequencesWithQuality] --input-path {input} --input-format PairedEndFastqManifestPhred33 --output-path {output}所有规则放到一个Snakefile里配合一个config.yaml文件保存样本列表、参数阈值、数据库路径等配置。这样整个流程就变成一条命令的事snakemake -n # 先预览要执行的任务 snakemake -j 8 --use-conda # 实际执行8核并行使用-n参数先干跑一遍是好习惯可以看到任务的执行顺序、会不会报文件路径错误避免直接跑半天才发现有一个输入路径写错了。4.2 参数配置与样本清单的经验我通常建议把样本信息单独维护一个manifest文件内容包括样本ID、正向/反向测序文件路径。建manifest文件时的常见坑是文件路径用了相对路径但运行目录和文件所在目录不一致导致导入失败。我的习惯是在项目根目录定义一个data/路径manifest里所有路径都写相对于项目根目录的路径。再用一个脚本检查所有FASTQ文件是否都真实存在减少不必要的报错等待。config.yaml里还有一个容易忽略的参数并行数--jobs。我们通常用8核或16核跑。但DADA2去噪时本身已经用了多线程如果再叠加Snakemake过多并行任务反而容易内存爆掉。建议DADA2阶段用4-6个子任务并行每个子任务分配4个CPU左右内存控制在16GB上下。4.3 断点续跑与异常恢复Snakemake最让我省心的一点就是“断点续跑”。比如跑注释时报错修好参数后直接再执行snakemake它只会重跑失败的那一步前面完成的步骤全部跳过。这在数据量大、单次运行超过十几个小时的场景里非常救命。但注意一个前提中间步骤的结果文件必须保留完整。results/目录不要每次运行前都清空Snakemake默认会根据文件时间戳判断是否需要重新生成目标文件一旦你手动删了中间文件它会老老实实地重算一大段流程。5 结果解读、可视化与报告输出5.1 从特征表到属级丰度表这一步必须做标准化拿到分类学注释结果后先有一个“特征表ASV表”。特征表里每一行是一个ASV每一列是一个样本单元格是序列数。但每个样本的测序深度不一样直接比较丰度没有意义所以要先做标准化。流程中的标准化方式是用qiime diversity core-metrics-phylogenetic来生成一系列标准化后的多样性结果它会根据采样深度做稀释。常用采样深度值是所有样本序列数的最小值但这里有个矛盾如果最小样本深度过低很多样本会被丢弃大量数据如果太高一些测序浅的样本会直接报错或被裁得极少。保险做法是先看每个样本的序列数分布去掉明显异常低或高的样本后再挑一个合理的中位数或分位数作为采样深度。对于一般土壤样本我们经常用20000-50000的采样深度对于拭子或者低生物量样本10000以下也很常见。标准化之后就可以做属级汇总了。QIIME2里可以用q2-taxa插件做barplot也可以导出到R做更细致的处理qiime taxa collapse \ --i-table table.qza \ --i-taxonomy taxonomy.qza \ --p-level 6 \ --o-collapsed-table genus-table.qza qiime tools export \ --input-path genus-table.qza \ --output-path exported-genus-table导出的生物表格是BIOM格式可以用biom convert转成TSV随后在R里再加工。5.2 属级可视化组合堆叠柱状图、热图和PCoA可视化阶段我比较喜欢三张图搭配着看。第一张是“属级堆叠柱状图”直观展示每个样本或分组的群落组成结构。第二张是“属级丰度热图”看哪些属在哪些样本中富集一目了然。第三张是“Beta多样性PCoA图”看样本间整体群落差异是否和实验分组一致。堆叠柱状图常用的R代码框架基于phyloseq和ggplot2library(phyloseq) library(ggplot2) ps - readRDS(phyloseq_object.rds) ps_genus - tax_glom(ps, taxrank Genus) ps_genus_plot - psmelt(ps_genus) %% group_by(Sample, Genus) %% summarise(Abundance sum(Abundance)) ggplot(ps_genus_plot, aes(x Sample, y Abundance, fill Genus)) geom_bar(stat identity, position stack) theme_classic() theme(axis.text.x element_text(angle 45, hjust 1))有一点值得特别注意如果直接画Genus级别的丰度图图例里很容易出现三四十个属颜色一多整个图就花了。我的建议是只保留平均相对丰度排前15-20的属其余归为“Others”图会清爽很多。PCoA的设置则主要关注距离算法。Bray-Curtis距离在生态学里用得非常普及能反映物种组成差异。想强调谱系关系时可以用UniFrac距离尤其是加权UniFrac它对丰度变化比较敏感。我通常会把加权与未加权的UniFrac都跑一遍再决定哪张图放进报告。5.3 差异属筛选与LEfSe的注意点组间差异属的筛选是很多研究报告里的重点。常用的策略是先做LEfSe分析线性判别分析找出组间差异显著的物种标记。我的经验是LEfSe的结果要结合实际丰度来解读因为有些差异属的平均相对丰度可能只有0.01%统计显著但实际生物学意义不大。在流程中我们会在LEfSe基础上再跑一遍基于DESeq2或ANCOM-BC的差异丰度分析两者交叉验证。只要两个方法都显著的属才放入最终报告。这个方法偏保守但能有效减少“假阳性属”的干扰尤其适合样本数量较少、组内波动较大的探索性研究。另外提醒一句做差异分析之前一定要把样本分组信息整理好。很多人在R里被卡住不是代码问题而是分组信息与样本ID不匹配。建议用sample_data统一管理并在读取数据时用all.equal(sample_names(ps), rownames(sample_data(ps)))检查一下。6 常见问题排查与优化实录6.1 低质量样本导致样品整体丢失第一次跑批量数据时我遇到一个很扎心的问题一批肠道样本有3个样本的reads在质控和去噪之后只剩不到几百条最终这些样本在特征表里几乎为空。排查时发现这批样本本身提取的DNA浓度很低测序产出差叠加质控参数偏严直接清洗没了。这里的经验是正式批量跑流程之前先用fastp和DADA2的质控报告看一下每个样本的reads通过率发现通过率低于30%的可以先提高质控的宽容度或直接标记为失败样本不要混进正式分析里拉低整体质量。低质量样本宁可剔除也不要硬留着。6.2 注释后出现大量“unknown genus”怎么办有段时间做极端环境样本注释结果里“unknown genus”的比例高达40%当时第一反应是数据库不够全面。后来排查发现问题出在前面的引物切除不完全——很多序列的5’端还残留着引物序列导致分类器在匹配时产生了偏移。重新完整切完引物并清理序列后unknown比例降到了10%左右。这个坑提醒我注释结果变差不一定都是分类器的锅先检查序列本身干不干净。另外如果之前用的是SILVA数据库可以再换GTDB试试因为GTDB对未培养类群的划分和命名相对更细致有时候能提高属级注释率和分辨率。6.3 单属主导造成的可视化失真还有一个常见情况某些样本里某个属比如乳酸菌属相对丰度占比超过80%这时候画堆叠柱状图其他属全被压成一条细线视觉上完全看不清。这个现象在发酵样本和肠道样本里尤其常见。我的处理方式是在热图部分用log10标准化后再画或者在堆叠图里保留“Top 10Others”组合并额外画一张“按丰度前50的属聚类”的热图这样主导属不会掩盖其他低丰度属的信息。如果还想突出稀有属的变化可以在差异分析里单独筛一遍低丰度但组间显著的属用气泡图展示。6.4 流程运行时间过长的优化整套流程跑96个样本如果全部单线程执行可能需要二十多个小时。经过几轮调优我把整体时间控制在4-6小时以内主要做了三件事第一质控和拼接阶段fastp启用多线程每个样本分配2-4个CPU第二DADA2的denoise步骤按样本切片并行但每个子任务分配的内存要足够避免swap第三分类注释阶段使用classify-sklearn时增大--p-reads-per-batch的批大小同时控制并行度防止内存溢出。另外可以在Snakemake里对不同规则设置不同的threads和resources让哪些步骤吃CPU、哪些步骤吃内存都一目了然。调优之后省下来的时间足以做更多轮参数探索和结果检查从整个项目周期来看非常划算。整套流程跑顺之后我最深的体会是分析流程的价值不只是“跑出结果”而是让你对每一步的数据变化心里有底。以前我处理完一批数据总有一堆说不清楚的中间环节现在无论是回溯参数、重现注释结果还是查某条序列为什么被过滤都能快速定位到具体位置。最后的经验分享新建项目时把原始数据、质控报告、参数配置、软件版本、运行日志全部归到一个项目目录里三周后你再看这些文件会感谢当时的自己。这比任何花哨的分析技巧都实在。
返回列表