1. RNA-seq分析概述与Nextflow简介

各位好,我是做生物信息学的老徐。今天开始咱们一起啃一个完整的案例——RNA-seq 定量分析流程,并且用 Nextflow 把它管起来。

RNA-seq,说白了就是给细胞里所有的 RNA 分子拍张“身份证照”,然后数一数每种 RNA 有多少份。这个数出来的结果,就是我们常说的“表达量”。你想想看,一个样本几千万条短读序列(reads),人工一条条数?不现实。所以我们需要一套自动化的流程,把原始测序数据转成基因/转录本的定量结果。

我个人习惯先把整体框架画出来,就像造房子先看图纸。下面这张图就是 RNA-seq 定量分析的核心步骤,也是咱们这个课程要动手搭建的骨架。

RNA-seq 定量分析核心流程 原始 FASTQ 质量控制 (FastQC) 比对/准比对 (STAR/Salmon) 表达定量 (featureCounts/Salmon quant) 多样本表达矩阵合并 差异表达分析 (DESeq2/edgeR) 注意:每个步骤都可能依赖多个软件,手动串联容易出错 —— 这正是 Nextflow 解决的痛点。

RNA-seq 定量分析到底在做什么?

很多新人会混淆“定量”和“差异分析”。咱们这章先把边界划清楚:定量是计算每个基因/转录本在样本中到底有多少条 reads 支持它。差异表达比较,是拿到定量结果之后的事。

定量分析通常包括三步:

  • 原始数据预处理:去除低质量碱基、接头序列,得到干净的 FASTQ 文件。
  • 比对或准比对:将 reads 映射到参考基因组或转录组。经典工具有 STAR、HISAT2,准比对类有 Salmon、kallisto。
  • 计数或定量:统计比对到每个基因/转录本上的 reads 数,或直接基于准比对得到丰度估计。

对了,提个坑:我在项目中遇到过,有些新手直接用默认参数跑 Salmon,忽略了 library type 设置。结果表达量估算全反了——明明应该链特异,结果当成非特异来估。后来排查了两天才发现,嗯,参数没看对。

我的经验: 做定量前一定要搞清楚测序文库的构建方式(单端/双端、链特异方向性)。这一步错了,后面的差异分析全是废的。

为什么要引入工作流管理?

以前我跑 RNA-seq 定量,都是写一堆 shell 脚本,用 for 循环遍历样本。看起来挺简单对吧?但你想想看:

  • 服务器重启后,脚本跑到一半中断了,你不知道哪些步骤完成了,哪些没完成。
  • 换了参考基因组版本,需要重新生成索引,手动改脚本里的路径很容易漏改。
  • 想用不同的参数再跑一次?只能复制一份脚本,但修改起来心惊胆战。

这都是血泪史。我曾经因为路径写错,把前一版结果覆盖了,重算花了整整两天。从那以后,我就开始找能自动管理依赖、断点续跑、容器化封装的工作流工具。

说白了,工作流管理工具解决了三个核心问题:

  1. 可重复性:所有步骤、参数、环境都写死在配置中,换了机子也能复现。
  2. 自动化:输入样本列表,输出表达矩阵,中间出错自动重跑或跳过已完成步骤。
  3. 并行计算:多样本自动并行,又能保证单样本内部的串联依赖正确。

Nextflow 初印象

业内比较流行的工作流工具,我接触过 Snakemake、CWL、WDL,但用得最顺手的还是 Nextflow。它有几个独到之处:

  • 原生支持 Docker/Singularity 容器,解决环境依赖问题。
  • 自动缓存中间结果,修改参数后只重新运行受影响的步骤。
  • 对 HPC 和云平台(AWS Batch、Google Cloud)支持友好。
  • 语法类似 Groovy,比纯粹 Python 的 Snakemake 更灵活。

核心概念速览:

概念一句话解释
process一个计算任务,比如“运行 FastQC”
channel数据流管道,用来传递文件、参数
workflow把多个 process 串联起来的逻辑结构
config配置文件,指定执行引擎、资源、容器镜像

举个例子,最简单的 Nextflow 脚本长这样:

#!/usr/bin/env nextflow

process FASTQC {
    input:
    path read
    output:
    path "*.html"
    """
    fastqc $read
    """
}

workflow {
    FASTQC( Channel.fromPath("data/*.fastq.gz") )
}

看到没?process 定义了一个任务,workflow 把输入通道和 process 连起来。几行代码就实现了批量跑 FastQC。而且 Nextflow 会自动帮你管理中间文件,下次再跑,如果输入没变化,它就直接跳过——这个叫缓存复用。

注意: 上面的脚本只是一个玩具,实际生产需要声明资源、容器、错误策略等。我们在后面的章节会一步步完善。

一个小对比:传统 shell 脚本 vs Nextflow

为了让你更直观地感受下差异,我列了个表格:

方面Shell 脚本Nextflow
中断恢复需要手动检查 && 逻辑自动缓存,断点续跑
环境隔离依赖系统全局库通过容器做到完全隔离
多样本并行自己写 & 或 GNU parallel自动分发,内置调度器
参数管理散落在脚本各处集中到 nextflow.config
可读性一长串管道命令模块化 process,含义清晰

我个人倾向:如果是几个样本、一次性实验,shell 完全够用。但一旦涉及 10+ 样本、多条件对比、需要在不同集群上迁移,Nextflow 的优势就完全压倒了。