肿瘤WES项目实战演练分享及学习班通知
日前在朋友圈发布了非常好的一个肿瘤WES项目测序文件的质控谍照,如下:
很多人留言感兴趣这个是哪家公司测序的,但事实上,这是一个公共数据,来自于2018年发表的单细胞DNA测序数据文章,我只是纯粹感兴趣就找到了众多问过我 GATK问题的粉丝,嘱咐他们试一下这个数据集的肿瘤wes分析,也因此结识了南方医优秀的小伙伴,在大家的热情呼唤下邀请他加入了我们VIP群:
回顾问过Jimmy的8个问题
下面是他实战该肿瘤WES数据分析项目的一点心得体会和记录,如果你坚持看到最后,请留意我们的肿瘤WES学习班通知哦!
Raw fastq QC(质控)
Alignment(比对)
Germline variants calling(胚系突变流程)
Create exon interval bed文件
BQSR
HaplotypeCaller & Joint genotype
VQSR
Somatic Variants Calling(体细胞突变流程)
Create PoN
Mutect2 calling
annovar注释
somatic的可视化结果
后记
0
背景
数据来源于这篇文章:Multiclonal Invasion in Breast Tumors Identified by Topographic Single Cell Sequencing。
来自10个乳腺癌患者的normal、INV、DCIS组织的exon测序结果,30个样本。
当然文章里还有其他很多数据,例如45万X的超高深度测序数据,果然又是彻底不用愁经费的团队。
我知道GATK很慢,但没想到下数据更慢。(充分说明了外网的重要性,或者高级工具aspera)
从12月12日开始下数据,学校小水管润物细无声,到了12月25日圣诞节才可以开始分析。
以下是处理过程的简要记录,包括主要步骤和参数,以及个人的浅薄理解。
如有错漏,还请大佬指正。
说明:因为30个samples,批量跑的,所以代码中很多输入参数都用变量代替。
1
Raw fastq QC
拿到sra,转完 fastq 先做了质控。
样本量有点多,跑完 fastqc 再用 multiQC 统一看质量。
原始数据应该是有过处理的。因为长度不统一,长度分布从80b到100b。
总的来说:还有illumina接头残留。大部分数据尾部质量一般,需要去接头,然后过滤下质量。
__________________________________________
SRR6269851 样本的质量
用 trim_galore
去接头以及过滤低质量碱基, trim_galore
利用 Cutadapt
完成去接头和低质量碱基的工作,所以环境变量里需要有cutadapt。
trim_galore --length 50 \
--stringency 5 \
-q 25 \
-e 0.1 \
--paired \
--phred33 -o $output_dir \
$read_1 $read_2
实际使用下来发现adapt去得很干净,但是质量改善效果一般。
这和trim的原理有关—— 碱基score减去阈值,然后从末端往回累加,直到累加之和大于0,这时候对应的碱基之后都会被剪掉。
对于不是很糟糕的数据,一般不会剪掉很多。不过越靠近末端剪得越多,所以尾部剪得比较干净。
__________________________________________
SRR6269851 样本trim后的质量
2
Alignment
接下来用 BWA mem
把fastq map到参考基因组 hg38 版本。
比对结果直接通过管道传给samtools处理,节省 I/O 时间。
再用 MarkDuplicates 去重复,picard集成在GATK里了(实际上是标记没有删掉,也改成可以rm模式)。(当然,这里也可以使用高级工具,sambamba)
然后把原来的bam删掉。节省磁盘空间。
bwa mem -t 8 -M -R "@RG\tID:${RGID}\tPL:${PL}\tLB:${SM}\tSM:${SM}" \
${ref_genome} \
${read_1} \
${read_2} | samtools sort -@ 4 -m 10G -o \
${output_dir}/sm_${SM}.hg38.sort.bam
$gatk MarkDuplicates \
-I ${output_dir}/sm_${SM}.hg38.sort.bam \
-M ${output_dir}/sm_${SM}.markdup.metrics.txt \
-O ${output_dir}/sm_${SM}.markdup.bam \
&& rm ${output_dir}/sm_${SM}.hg38.sort.bam
习惯给每个sample前面加上前缀,这样方便以后的匹配处理。例如 sm_
代表sample, T
、 N
代表tumor、normal。
如果每个样本有多个bam这时候可以merge成一个bam本文件。
3
Germline variants calling
3.1 Create exon interval bed文件
由于是外显子测序,把关注区域聚焦到 wes region。
一开始我是从GTF提取全部exon位点的,想法是外显子测序嘛,那就全部exon区域都看。
后来想想对于那些 lncRNA 的 exon 上的 SNP,不是说没用,而是一般实验室最后关注点都是落在基因上的 variants ,那其实只提取 CDS region 也可以了。
其实我问了实验的同学,她们也没有具体说明到底外显子测序是真的测全部exon,还是只测到CDS中的外显子。她们只是说通过探针捕获目标区域再测序。不过的确是,大家都忙,没有时间和精力每个细节都亲自去研究。(其实应该是看WES芯片的bed文件)
3.2 BQSR
按照GATK的说法,测序机器对质量会有系统性的误差。
例如:假设机器在连续call了两个AA碱基后,后面的一个碱基质量score会偏高10%。那我们就可以反过来对AA后一个碱基score降低10%点。(这个是为了方便理解,不是真的这么简单)
而 variant calling 需要考虑 base quality,所以GATK推荐对碱基质量进行校正。
另外校正碱基质量不是改善碱基质量,不是让 low score -> high score 而是要 让 incorrect score -> correct score。
$gatk BaseRecalibrator \
-R ${GATK_bundle}/Homo_sapiens_assembly38.fasta \
-I ${output_dir}/sm_${SM}.markdup.bam ${Interval_list} \
--known-sites ${GATK_bundle}/Homo_sapiens_assembly38.known_indels.vcf.gz \
--known-sites ${GATK_bundle}/Homo_sapiens_assembly38.dbsnp138.vcf\
--known-sites ${GATK_bundle}/Mills_and_1000G_gold_standard.indels.hg38.vcf.gz \
-O ${output_dir}/sm_${SM}.BQSR.table
$gatk ApplyBQSR \
--bqsr-recal-file ${output_dir}/sm_${SM}.BQSR.table \
-R ${GATK_bundle}/Homo_sapiens_assembly38.fasta \
-I ${output_dir}/sm_${SM}.markdup.bam ${Interval_list} \
-O ${output_dir}/sm_${SM}.ApplyBQSR.bam
先计算哪些需要更正,然后再调整,之后生成的bam 文件会比原bam更大,这是因为
Base recalibration adds insertion and deletion tags, so that will increase the size of your bam file. --GATK team
对于是否有必要做这一步呢,个人是持不算积极的态度的,如果时间紧张我会跳过,因为感觉这个位点85%是A和98%是A都是一个估算,而45%是A和55%是A对我来说又同样是不可信。
时间上:平均10G+ 的 clean bam文件,先第一步 BaseRecalibrator 用了 1+hr,之后 ApplyBQSR 用了 1+hr,
3.3 HaplotypeCaller & joint genotype
先生成gvcf,再联合分析方便增量分析:
aplotypecaller 就做了这么几件事:(说得好像很简单)
找出高变异的活跃区域
组装出可能的基因型
pairHMM确定每条read可能是那种基因型
最后确定sample的genotype
HP过程很耗时间,而且GATK4.0里面没有提供多线程的设置。取消了 -nct 参数设置
但其中pairHMM这一步是可以进行多线程加速的 ,指定 --native-pair-hmm-threads
$gatk HaplotypeCaller \
--native-pair-hmm-threads 4 \
-R ${ref_genome} \
${Interval_list} \
-I ${output_dir}/sm_${SM}.ApplyBQSR.bam \
-O ${output_dir}/gvcf/${SM}.g.vcf.gz \
-ERC GVCF
samples=(${gvcf_dir}/N*.g.vcf.gz)# 给每个normal sample前加了 N 方便匹配
# 多个--variant参数输入可以通过shell元组解决
$gatk CombineGVCFs \
-R ${ref_genome} \
${samples[@]/#/--variant } \
-O ${gvcf_dir}/cohort_${num}_g.vcf.gz
$gatk GenotypeGVCFs \
-R ${ref_genome} \
-V ${gvcf_dir}/cohort_${num}_g.vcf.gz \
-O ${vcf_output}/unfilter_cohort_${num}.vcf.gz
这部分用的时间:13+ 个小时
3.4 VQSR
上步得到的VCF需要进行过滤,降低假阳性。
VQSR要提供很多已知数据信息,以及繁琐的 -an
参数。
SNP 和 INDEL 可以分开过滤,也可以一起过滤。如 -mode BOTH
$gatk VariantRecalibrator \
-R ${ref_genome} \
-V ${vcf_output}/unfilter_cohort_${num}.vcf.gz \
--resource hapmap,known=false,training=true,truth=true,prior=15.0:${GATK_bundle}/hapmap_3.3.hg38.vcf.gz \
--resource omni,known=false,training=true,truth=false,prior=12.0:${GATK_bundle}/1000G_omni2.5.hg38.vcf.gz \
--resource 1000G,known=false,training=true,truth=false,prior=10.0:${GATK_bundle}/1000G_phase1.snps.high_confidence.hg38.vcf.gz \
--resource dbsnp,known=true,training=false,truth=false,prior=2.0:${GATK_bundle}/Homo_sapiens_assembly38.dbsnp138.vcf \
--resource mills,known=false,training=true,truth=true,prior=15.0:${GATK_bundle}/Mills_and_1000G_gold_standard.indels.hg38.vcf.gz \
-an QD -an MQ -an MQRankSum -an ReadPosRankSum -an FS -an SOR \
-mode BOTH \
-O ${work_dir}/log/${num}_SNP_INDEL.VQSR.recal \
--tranches-file ${work_dir}/log/${num}_SNP_INDEL.VQSR.tranches \
--rscript-file ${work_dir}/log/${num}_SNP_SNP_INDEL.VQSR.plots.R
最后会用R画结果图,所以需要提取装好 R
和 ggplot2
4
Somatic Variants Calling
4.1 Create PoN
对 somatic variants calling 朴素的理解是:从检测到的variants里尽可能地去掉germline 、common variants。
在进行somatic variants前,需要先用mutect的tumor模式创建 panel of normal。
mutect其实包含了HP过程在里头,所以也是耗时间大户。
$gatk Mutect2 \
-R ${ref_genome} \
-I ${work_dir}/output/sm_N${sm}.ApplyBQSR.bam \
-tumor ${sm} \
--disable-read-filter MateOnSameContigOrNoMappedMateReadFilter \
-L ${Interval} \
-O ${PoN_dir}/sample/${sm}.vcf.gz
disable-read-filter 选项避免把没有properly mapped的reads丢掉。
创建Panel of normal,同样利用shell元组解决多个输入的问题。
samples=(${PoN_dir}/sample/*.vcf.gz)
$gatk CreateSomaticPanelOfNormals \
${samples[@]/#/-vcfs } \
-O ${PoN_dir}/PoN.vcf.gz
4.2 Mutect2 calling
$gatk Mutect2 \
-R ${ref_genome} \
-I ${work_dir}/output/sm_INV_${sm}.ApplyBQSR.bam \
-I ${work_dir}/output/sm_N_${sm}.ApplyBQSR.bam \
-tumor ${tumorsampletag} \
-normal ${tumorsampletag} \
-pon ${PoN_dir}/PoN.vcf.gz \
--germline-resource ${germline_resource} \
--af-of-alleles-not-in-resource 0.0000025 \
--disable-read-filter MateOnSameContigOrNoMappedMateReadFilter \
-L ${Interval} \
-O ${somatic_vcf}/vcf/INV.${sm}.somatic_unfilter.vcf.gz \
${tumorsampletag}
tumorsampletag
分别对应normalsample和tumorsample bam文件header里的sample记录信息。
${germline_resource}
来自 gnomAD resource,包含了~200K exomes测序的 allele-sepcific population frequency信息。作为参考的population germline AF。
${Interval}
是WES interval 的bed文件。
和germline过程一样,需要过滤。
首先 GetPileupSummaries 收集每个突变位点上ref 和 alt 的支持reads 数量。
calculatecontamination 估计样本cross contaminated的程度。这里的样本交叉是指不同sample间的污染不是normal和tumor间的污染。
$gatk GetPileupSummaries \
-I ${work_dir}/output/sm_${sm}/*.ApplyBQSR.bam \
-V ${resource} \
-L ${Interval} \
-O ${filter_dir}/table/${sm}.getpileupsummaries.table
$gatk CalculateContamination \
-I ${filter_dir}/table/${sm}.getpileupsummaries.table \
-O ${filter_dir}/table/${sm}.calculatecontamination.table
sm1=${sm%%_*}.${sm##*_}
$gatk FilterMutectCalls \
-V ${work_dir}/somatic/vcf/${sm1}.somatic_unfilter.vcf.gz \
--contamination-table ${filter_dir}/table/${sm}.calculatecontamination.table \
-O ${filter_dir}/vcf/${sm}.filter.vcf.gz
过滤完的VCF中会有对应的 PASS 标记,可以提取行。
awk -F '\t' '{if($0 ~ /\#/) print; else if($7 == "PASS") print}'
5
annovar注释
annovar是个perl脚本;用学校教育邮箱即可以注册获取下载链接
这里只注释到gene上,没有注释到SNP信息
./table_annovar.pl ${sm} ./hg38_humandb/ \
-buildver hg38 -out $n \
-remove -protocol refGene,cytoBand \
-operation g,r -nastring . -vcfinput
产生三种文件:
annovar的avinput文件
注释后的vcf
注释后的结果txt
其中txt和vcf内容一致。
最后R中用 maftools
可视化。 maftools
的具体使用可参考往期 :
6
somatic的可视化结果
与之前处理过的肝癌和膀胱癌症相比,发现乳腺癌每个患者的突变数量要少,如果算TMB应该也不高。
这里看到 patient 1 、8 的突变数目最少。
乳腺癌中最多的是C>A突变,其次C>T突变,不同癌症的情况也会不同。(这样的突变模式是研究的热点,我在直播我的基因组活动中多次强调)
除开1、8号patient,同一个患者的INV和DCIS样本都存在一致的高频突变,从这点出发也可以旁证下肿瘤的亚克隆进化。
这里是只展示突变率前30的突变,所以容易给人错觉:patient 8 没有突变。但其实只是patient 8 的突变恰好不是高频突变而已。
频突变基因的词云。不得不说maftools真是便利。
最后还有不同基因的突变事件是否显著共发或者互斥。
一趟下来,拿到了germline的vcf和somatic的vcf,也对somatic VCF做了注释和可视化。
当然后续还有CNV没做。而且这只是一次基础流程的实践,偏向于简略地记录个人步骤和浅簿理解。
中途有缺漏谬误,请大家多多指正。
7
后记
接触GATK已经有2个多月了。越来越觉得一套分析流程,要跑下来没报错很容易,难点在于理解为什么,以及针对自己的数据贴身修改。还有的是要保证结果的可信度。
最担心是程序虽然没报错,但拿到不可靠的结果。
比如参数不合理,数据输入混淆,参考注释版本不同、未标化当成以及标准化等等,这些地方弄错,程序没有报错,最后自己也没发现。
另外越来越觉得 数理统计、编程能力和对生物学问题的敏感性 是始终绕不开的核心。
果然别人的经验是不会骗你的,至于各类分析流程,应该看成随着任务不同而不断换用的工具。
混好生信和湿实验一样,得问题出发、思路先行,再结合工具方法回答问题。
8