二代群体遗传与重测序(上)

上已完结,中见https://www.jianshu.com/p/0147afc3334c

零.软件安装

singularity实在太方便了。这个问题后面再更

一.变异分析

技术路线:bwa进行参考基因组比对→samtools和picard排序和去除重复,以免造成duplication干扰→GATK的变异检测:HaplotypeCaller分样本变异检测,GenomicsDBImport(各样品)以数据库合并,GenotypeGVCFs分染色体鉴定,MergeVcfs合并各染色体→GATK提取和过滤SNP与InDel→lumpy-sv等鉴定SV→CNVnator等鉴定CNV

GATK pipeline

01.参考基因组index构建

• 文件准备:
参考基因组genome.fasta

$ ln -s ../data/genome.fasta
$ samtools faidx genome.fasta
$ bwa index genome.fasta
$ java -jar /opt/picard.jar reateSequenceDictionary R=genome.fasta#使用的是容器中的路径
#hisat2-build  genome.fasta genome.fasta

picard软件建立后面GATK所需要的dict文件,hisat2-build用于转录组的内容(本文无需)。

02.比对参考基因组与去重复

• 文件准备:
S1_1.fq.gz 等双末端测序文件
样品信息表sample.list,记录了样品名称和双末端测序.fq.gz文件的路径。
如果有更多序列需要进行比对的话可以仅修改sample.list的内容来获得更多脚本再一并运行。即使sample.list中的内容有错也能顺利生成脚本,但脚本不能运行。

$cat sample.list 
S1      ../data/S1_1.fq.gz      ../data/S1_2.fq.gz
S2      ../data/S2_1.fq.gz      ../data/S2_2.fq.gz

用一个脚本来生成一堆脚本,再批量运行那一堆脚本来扩展可读性。所生成的单个脚本用于一个样本的比对过程。

#!/bin/bash 

ref=../01.ref/genome.fasta

cat sample.list |while read  sp fq1 fq2 
do 
    echo   " 

#比对之后排序并生成bam文件
bwa mem -t 2 \ #-t线程数
-R '@RG\tID:$sp\tSM:$sp\tPL:illumina' #添加read group信息
$ref  $fq1  $fq2  \
2>$sp.bwa.log |  \ #比对日志
samtools sort -@ 2 \#线程数
-m 1G \#每个线程内存大小
-o $sp.sort.bam - #指定输出文件的名称

#去除重复
java -Xmx4g -XX:ParallelGCThreads=2 -jar \#java的运行参数
/opt/picard.jar   MarkDuplicates I=$sp.sort.bam\#调用软件
O=$sp.sort.markdup.bam  \
CREATE_INDEX=true  \
REMOVE_DUPLICATES=true \#把PCR重复部分删掉
M=$sp.marked_dup_metrics.txt

#将bam文件中的flag信息提取出来
samtools  flagstat  $sp.sort.bam > $sp.sort.bam.flagstat

#覆盖度情况
samtools  coverage  $sp.sort.bam > $sp.sort.bam.coverage
" >   mapping.$sp.sh 
done

需要用bash来运行该脚本,否则\t等正则表达式会被转义。samtools软件用于查看和提取比对信息,nohup执行一定要把日志文件分开储存。picard用于去除PCR重复
运行所生成的脚本文件之后,输出应该包括如下内容:

mapping.S1.sh的输出文件

$ cat S1.sort.bam.flagstat 
802975 + 0 in total (QC-passed reads + QC-failed reads)
800000 + 0 primary
0 + 0 secondary
2975 + 0 supplementary
0 + 0 duplicates
0 + 0 primary duplicates
793472 + 0 mapped (98.82% : N/A)
790497 + 0 primary mapped (98.81% : N/A)
800000 + 0 paired in sequencing
400000 + 0 read1
400000 + 0 read2
751324 + 0 properly paired (93.92% : N/A)
781016 + 0 with itself and mate mapped
9481 + 0 singletons (1.19% : N/A)
1432 + 0 with mate mapped to a different chr
1144 + 0 with mate mapped to a different chr (mapQ>=5)

记录的数量会比输入的序列数量多一些,也就是出现了多比对的情况。总共有98.82%的序列能比对上,去掉多比对还剩98.81%(在文章中应该使用该值)。高质量比对占93.90%.

03.SNP和indel鉴定

• 文件准备:
基因组文件:genome.fasta
比对结果文件:S1.sort.markdup.bam等
使用GATK来得到群体变异的检测结果

分染色体生成GVCF文件
$ mkdir tmp/
$ mkdir S1
#S1样品 chr1染色体
$ gatk --java-options "-Xmx10g -Djava.io.tmpdir=./tmp" \#设置Java参数和临时文件路径
 HaplotypeCaller -R ../01.ref/genome.fasta  \#参考基因组
 -I  ../02.mapping/S1.sort.markdup.bam \ #bam文件路径 
 -L chr1  \#指定染色体名称
 -ERC GVCF \#输出GVCF用于后面的群体变异检测
 -O S1/S1.chr1.g.vcf.gz \ #gatk会根据输出后缀决定是否压缩
 1>S1/S1.chr1.HC.log   2>&1 #日志文件中可以查看进程
$ mkdir S2  
#S1样品 chr2染色体 参数同上
$ gatk --java-options "-Xmx10g -Djava.io.tmpdir=./tmp" HaplotypeCaller -R ../01.ref/genome.fasta  -I ../02.mapping/S1.sort.markdup.bam -L chr2  -ERC GVCF -O S1/S1.chr2.g.vcf.gz 1>S1/S1.chr2.HC.log   2>&1 

此处等待时间较长,长达数日那种。可以在日志文件中查看自己的运行进度。warning不重要
HaplotypeCaller是GATK中特殊的一个步骤。其他软件更多使用reads的覆盖情况和碱基型的频率直接输出结果。HaplotypeCaller会先鉴定变异活跃区域,再通过局部组装(德布鲁因图)来去掉覆盖少的变异。然后确定每条reads单倍型的似然值,最后用bayes来确定genotype的后验概率。

$tail S1/S1.chr1.HC.log
合并GVCF文件

相比包含变异位点的VCF文件,GVCF还包含了未变异位点的信息,但没有genotype信息
输入数据来自上一步的输出,获得待combine的GVCF文件路径
生成chr1染色体map文件。awk从路径中提取样品名称,路径名来自上一个脚本。

##抓取chr1的路径名称
$ ls ./*/*.chr1.g.vcf.gz | awk -F "/" '{print $2"\t"$0}' > gvcf.chr1.map
$cat gvcf.chr1.map
S1 ./S1/S1.chr1.g.vcf.gz
S2 ./S2/S2.chr1.g.vcf.gz

先构建GenomicsDB,适合样品较多的情况,比如超过四五百(官方建议是一千)。其他染色体的脚本也可以参照类似之

## 生成chr1染色体的genomeDB
$ gatk --java-options "-Xmx10g -Djava.io.tmpdir=./tmp \
-DGATK_STACKTRACE_ON_USER_EXCEPTION=true" \#参数必加!!
GenomicsDBImport \ #构建DB
--sample-name-map gvcf.chr1.map \ # 指定map文件名称
--genomicsdb-workspace-path genomeDB.chr1 \ # genomeDB目录名称
-L chr1 \ # 指定染色体
--reader-threads 1 \ # 线程数
--batch-size 50 \ # 每次读取文件个数。如果机器IO较少的话需降低该参数
--tmp-dir ./tmp \#临时文件目录
1>chr1.GenomicsDBImport.log 2>&1#日志文件和报错文件区分开
genomeDB.chr

保证文件目录正常生成就可以了

分染色体的变异检测
$ gatk --java-options "-Xmx10g -Djava.io.tmpdir=./tmp" \
GenotypeGVCFs \#变异检测
-R ../01.ref/genome.fasta \#参考基因组路径
-V gendb://genomeDB.chr1 \#输出结果的名字
-O chr1.raw.vcf.gz \
1>chr1.GenotypeGVCFs.log 2>&1

结果在chr1.raw.vcf.gz中,可以用less -S查看

合并成全基因组 vcf 文件

也可以字符串拼接或者手动输入raw_vcf.list

$ awk '{print $1".raw.vcf.gz"}' chr.list > raw_vcf.list#生成VCF文件列表
$ cat raw_vcf.list
chr1.raw.vcf.gz
chr2.raw.vcf.gz
$  gatk --java-options "-Xmx10g -Djava.io.tmpdir=./tmp" \
MergeVcfs \
-I raw_vcf.list \ #所需要merge的列表
-O all.merge_raw.vcf.gz

该文件也可以不压缩,因为要最终应用于后面的选择分析等步骤。样品量过多时仍然要花一些时间。

提取和过滤SNP和InDel
$ gatk --java-options "-Xmx4g -Djava.io.tmpdir=./tmp" \
SelectVariants \#筛选SNP
-R ../01.ref/genome.fasta \
-V all.merge_raw.vcf \
--select-type SNP \
-O all.raw.snp.vcf

这样就把snp给筛选出来了,下一步进行hard filter

###加标记
$ gatk --java-options "-Xmx4g -Djava.io.tmpdir=./tmp" \
VariantFiltration \
-R ../01.ref/genome.fasta \
-V all.raw.snp.vcf \
--filter-expression "QD < 2.0 || MQ < 40.0 || FS > 60.0 \
|| SOR > 3.0 || MQRankSum < -12.5 || ReadPosRankSum < -8.0" \#指定过滤的标准,此处使用的是gatk的推荐标准
--filter-name 'SNP_filter' \#满足以上任意一个标准就会加上一个标记
-O all.filter.snp.vcf

### 提取过滤好的SNP
$ gatk --java-options "-Xmx4g -Djava.io.tmpdir=./tmp" \
SelectVariants \
-R ../01.ref/genome.fasta \
-V all.filter.snp.vcf \
--exclude-filtered \#不要有标记的
-O all.filtered.snp.vcf

后面可以基于标记来过滤掉低质量snp。高质量snp.vcf将用于后续的一系列分析。在加标记的时候,纯合位点会因为无法去进行针对杂合位点的检测而warn
现在的vcf文件中的FILTER列会出现标记,而非之前的占位点。
复杂度只有O(n),运行速度会很快。

接下来同理提取和过滤InDel,只需要改动过滤标准

### 提取INDEL
$ gatk --java-options "-Xmx4g -Djava.io.tmpdir=./tmp" \
SelectVariants \
-R ../01.ref/genome.fasta \
-V all.merge_raw.vcf \
--select-type INDEL \
-O all.raw.indel.vcf
### 过滤INDEL(Filter列加标记)
$ gatk --java-options "-Xmx4g -Djava.io.tmpdir=./tmp" \
VariantFiltration \
-R ../01.ref/genome.fasta \
-V all.raw.indel.vcf \
--filter-expression "QD < 2.0 || FS > 200.0 || SOR > 10.0 \
|| MQRankSum < -12.5 || ReadPosRankSum < -8.0" \
--filter-name 'INDEL_filter' \
-O all.filter.indel.vcf
### 提取过滤好的INDEL
$ gatk --java-options "-Xmx4g -Djava.io.tmpdir=./tmp" \
SelectVariants \
-R ../01.ref/genome.fasta \
-V all.filter.indel.vcf \
--exclude-filtered \
-O all.filtered.indel.vcf

非染色体水平的测序数据
可以利用iTools中的fatools中的regenerate功能,先转成带有假的染色体水平的序列。

$ iTools Fatools regenerate -InPut genome.fasta -OutPut new.fast -NewChr Chr -InserN 1000 -NumSeq 20

会生成带有染色体信息的序列,和原始contig和chr的对应关系和位置的文件。后者可以用于把这个假文件转回原来的真文件。

04.SV的鉴定与分型

·文件准备:
基因组文件:genome.fasta
比对结果文件:S1.sort.markdup.bam S2.sort.markdup.bam
基于比对结果和深度信息,用lumpy来寻找sv和cnv位点;svtyper对样品分型(genotyping);svtools把个体水平sv信息整合为群体水平信息。

$ samtools view -b -F 1294 ../02.mapping/S1.sort.markdup.bam >S1.discordants.bam

先按照flag规则(-F 1294)提取单个bam文件中的变异信息,排除正常比对的reads。

$ samtools view -h ../02.mapping/S1.sort.markdup.bam | extractSplitReads_BwaMem -i stdin | samtools sort -> S1.splitters.bam

提取分裂比对的reads(extractSplitReads_BwaMem -i stdin)

$ lumpyexpress -P \#把prpos和prend信息输出,作为群体SV鉴定的依据
-B ../02.mapping/S1.sort.markdup.bam \
-S S1.splitters.bam \ #提取分裂比对
-D S1.discordants.bam \ #提取不正常比对
-o S1.lumpy.vcf

SV鉴定,得到位置信息。

$ svtyper -i S1.lumpy.vcf \
-B ../02.mapping/S1.sort.markdup.bam \
-o S1.lumpy.gt.vcf

SV信息的分型。同理,对其他的样品,S2S3之类的也进行上述处理。

合并vcf

接下来基于多个样品的breakpoint进行分型。此处需要指定tmp目录,不要让它生成在默认tmp

$ mkdir  tmp
$ ls ./*.lumpy.gt.vcf  > vcf.list #合并之前所有的lumpy.gt.vcf
$ svtools lsort -f vcf.list \#对个体的sv检测结果排序
-t  ./tmp   >  all.lsort.vcf 
$ svtools lmerge \ #位置信息的合并(位置有重叠,但不完全一致)(利用之前-P参数的输出)
-i all.lsort.vcf -t ./tmp > all.lmerge.vcf
#重新进行单样品sv检测并输出分型信息
$ svtyper -i all.lmerge.vcf -B ../02.mapping/S1.sort.markdup.bam -o S1.merge.gt.vcf
$ svtyper -i all.lmerge.vcf -B ../02.mapping/S2.sort.markdup.bam -o S1.merge.gt.vcf

所有样本的genotype合并

$ ls ./*.merge.gt.vcf > merge.vcf.list
$ svtools vcfpaste -q\#让vcf里面的quality累加
 -f merge.vcf.list |\
sed 's/PR...=[0-9\.e,-]*\(;\)\{0,1\}\(\t\)\{0,1\}/\2/g'  > all.genotype.vcf

分型完成之后利用sed去掉pro信息

05.CNV检测

CNVnator处理之前要对基因组文件进行预处理,在一个新目录中把每一条序列都切分成一个文件

## step1 准备基因组文件
#链接文件到当前目录
$ ln -s ../data/genome.fasta ./genome.fa
#按染色体切分基因组
$ seqkit split -i ./genome.fa -O split
#批量修改基因组文件名称
$ ls ./split/genome.id_*.fa | sed 's/\.\/split\/genome\.id_//' | awk '{print "mv split/genome.id_"$1" split/"$1}' >mv_name.sh
$ sh mv_name.sh

root是CNVnator的一个依赖包,由于版本问题需要格外设置环境变量

$ export ROOTSYS=/pub/software/root
$ export PATH=/pub/software/root/bin:$PATH
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOTSYS/lib

运行cnvnator ,前后的bin size大小不变,如果修改的话要从头再来。

$ ln -s ../02.mapping/S1.sort.markdup.bam
## 提取比对结果,生成结果在S1.root中
$ cnvnator -genome genome.fa -root S1.root -tree S1.sort.markdup.bam
## 生成深度分布,窗口大小(bin size)为500
$ cnvnator -genome genome.fa -root S1.root -his 500  -d split
## 进行统计计算
$ cnvnator -root S1.root -stat 500
## 检查bin size是否合适,RD ratio为4~5之间为宜。不然的话最好修改之前的-his参数
$ cnvnator -root S1.root -eval 500  > S1.eval.ratio
##RD信号分割
$ cnvnator -root S1.root \
-partition 500 #指定参数使所有结果都集中在S1.root文件中
##CNV检测
$ cnvnator -root S1.root  -call 500 > S1.cnv

在S1.cnv文件中可以看到cnv检测的信息。包括变异类型、标准化深度、长度、pvalue等。最后一列是Q0,越大可信度越低,可以用q0<,CNVnatorP1<0.05来过滤。
可以通过cnvnator内置的一个软件包转化为熟悉的vcf格式来查看

$ cnvnator2VCF.pl S1.cnv  >S1.cnv.vcf

你可能感兴趣的:(二代群体遗传与重测序(上))