流程搭建基础:WDL/Cromwell 工作流简介、标准 GATK Best Practices 管线配置归纳总结

好了,进入第二章。

说实话,很多刚接触 GATK 的朋友,上来就急着跑变异检测命令,结果环境一换、数据一换,脚本就崩得一塌糊涂。我当年也吃过这个亏。所以咱们先不急着跑分析,先把流程的“骨架”搭起来——也就是理解 WDL 和 Cromwell,以及标准 GATK Best Practices 的管线是怎么组织的。

为什么要先讲这个?因为你一旦掌握了 WDL,GATK 的官方流程你就能直接看懂、直接改、直接跑。这比你自己从头拼 shell 脚本要靠谱得多。

2.1 为什么是 WDL + Cromwell?

GATK 团队官方推荐的工作流语言是 WDL,执行引擎是 Cromwell。说白了,WDL 负责描述“做什么、按什么顺序做”,Cromwell 负责“找机器、跑命令、管数据”。

我个人习惯把 WDL 看作“编程语言版的实验记录本”——每条分析步骤写得清清楚楚,输入、输出、参数、资源需求一目了然。而且它天然支持并行、容错,特别适合高吞吐的生信分析。

核心概念对照

概念WDL 中的角色我的理解
workflow定义流程整体就像一张流程图,把任务串起来
task定义单个分析步骤封装一个工具的命令和参数
call在 workflow 中调用 task跟函数调用差不多
runtime指定计算资源需求告诉 Cromwell 给我多少 CPU、内存
Cromwell工作流执行引擎调度器 + 执行器 + 日志系统

2.2 WDL 基本语法——够用就行

我不会教你写复杂的 WDL,我们只学能看懂 GATK 官方流程的语法就够了。嗯,大概七八个关键词,你就已经能改流程了。

记住这个结构模板

version 1.0

workflow MyGATKWorkflow {
  input {
    File my_bam
    File my_reference
  }
  call PreprocessBam {
    input: bam = my_bam, ref = my_reference
  }
  call CallVariants {
    input: processed_bam = PreprocessBam.output_bam, ref = my_reference
  }
  output {
    File final_vcf = CallVariants.variants
  }
}

task PreprocessBam {
  input {
    File bam
    File ref
  }
  command {
    gatk MarkDuplicates \
      -I ~{bam} \
      -O marked_dups.bam \
      -M marked_dup_metrics.txt
  }
  output {
    File output_bam = "marked_dups.bam"
  }
  runtime {
    cpu: 4
    memory: "16 GB"
  }
}

你看,WDL 的结构很直观:workflow 包裹整个流程,task 定义每个步骤。输入用 File 声明,引用变量用 ~{变量名}。就这么简单。

我个人经验:刚开始不要追求写出完美的 WDL。拿一个官方的 .wdl 文件下来,照着改改参数,跑一跑,比学语法快得多。

2.3 Cromwell 的配置——踩过的坑

Cromwell 本身就是一个 Java 程序,你用 java -jar cromwell.jar run workflow.wdl 就可以启动。但实际生产中,大家都会写配置文件来指定后端计算资源。我遇到过最坑的是:配置文件里没写镜像,结果 Cromwell 用本地环境跑,版本全对不上,跑了一天全白费。

避坑:Cromwell 配置必须写镜像

backend {
  default: "Local"
  providers {
    Local {
      actor-factory = "cromwell.backend.impl.sfs.config.ConfigBackendLifecycleActorFactory"
      config {
        concurrent-job-limit = 2
        runtime-attributes = """
        String? docker
        """
        submit = """
        docker run --rm -v ${cwd}:${cwd} ${docker} ${job_shell} ${command}
        """
      }
    }
  }
}

这个配置里最关键的一行就是 String? docker。它允许你在 WDL 的 runtime 块里指定 Docker 镜像。比如:

runtime {
  docker: "broadinstitute/gatk:4.4.0.0"
}

这样 Cromwell 就会拉取官方的 GATK 镜像,环境百分百一致。

2.4 标准 GATK Best Practices 管线——一张流程图说清楚

下面这张 SVG 图,是我把整个 GATK 种系变异检测管线(Germline short variant discovery)的核心流程画出来的。你仔细看,注意它是怎么从原始 BAM 一步步走到最终 VCF 的。

GATK Best Practices 种系变异检测核心流程 原始 BAM / FASTQ 数据预处理 MarkDuplicates → BaseRecalibrator → ApplyBQSR 变异检测 HaplotypeCaller → GenomicsDBImport(群体合并) 变异过滤与评估 VariantRecalibrator (VQSR) → ApplyVQSR 最终 VCF ⚠️ 常见误区 跳过数据预处理 直接用原始BAM 结果很糟糕

这张图里我标了四个核心阶段:数据预处理 → 变异检测 → 过滤评估 → 最终 VCF。每个阶段内部,用的工具都是 GATK 命令行工具。你记住这个流水线结构,再看官方 WDL 脚本就豁然开朗了。

2.5 标准管线配置归纳——一张表记住全部步骤

很多教程把 GATK Best Practices 讲得特别复杂。我把它归纳成下面这张表,你看一遍就能在心里搭起框架。

阶段工具主要功能关键参数
数据预处理MarkDuplicates标记 PCR 重复REMOVE_DUPLICATES=false
BaseRecalibrator学习碱基质量变异模型knownSites 数据库路径
ApplyBQSR根据模型重校准碱基质量--bqsr-recal-file
变异检测HaplotypeCaller单样本 gVCF 生成--emit-ref-confidence GVCF
GenomicsDBImport群体 gVCF 聚合--genomicsdb-workspace-path
GenotypeGVCFs联合基因分型--include-non-variant-sites
过滤评估VariantRecalibratorVQSR 模型训练--mode SNP / INDEL
ApplyVQSR应用过滤阈值--ts-filter-level 99.0
输出SelectVariants / CombineGVCFs格式化 & 合并--exclude-filtered

个人建议:刚开始跑 GATK 流程,不要贪多。先把 MarkDuplicates + HaplotypeCaller 这个最小闭环跑通,再逐步加上 BQSR 和 VQSR。一句话,先出结果,再谈优化。

2.6 常见坑与我的应对

  • 路径问题:WDL 里所有文件路径必须是绝对路径或者 Cromwell 能访问到的。我建议把所有输入统一放在一个inputs.json配置文件里,不要硬编码。
  • 镜像版本:GATK 大版本升级有时会改命令行参数。我吃过一次 4.2 到 4.4 迁移的亏,--emit-ref-confidence 参数变了,跑了一天才发现结果不对。
  • Cromwell 日志:默认日志在 cromwell-executions 目录下。流程卡死时,先看 stdout 和 stderr。

曾经我犯过的错误:有一次我把 docker 标签写错了,结果 Cromwell 默默使用本地环境,版本差异导致 HaplotypeCaller 运行时 OOM 崩溃。检查了半天才发现是镜像名少了个版本号。所以我现在每个 WDL 脚本的第一个 runtime 块,一定会写死镜像 tag,比如 broadinstitute/gatk:4.4.0.0。

好了,这一章的内容就到这。你把 WDL 的基础语法、Cromwell 配置要点、以及 GATK Best Practices 的标准管线结构理清楚,后面章节我们再深入每个参数怎么调优。就这样,下一段路咱们实地跑一跑流程。