WGS学习全流程笔记

作者: 天秤座的机器狗 | 来源:发表于2018-08-03 17:42 被阅读6次

    Part1 数据下载

    先去Korean Personal Genome Project下载了编号为KPGP-00001的数据。

    先说一下KPGP吧,中文名叫韩国个人基因组计划,这里面的数据都是可以免费下载的。

    image image image
    
    nohup wget  -c -r -nd -np -k -L -p   ftp://ftp.kobic.re.kr/pub/KPGP/2015_release_candidate/WGS/KPGP-00001  1>/dev/null  2>&1 &
    
    

    简单的说一下这个命令中的几个知识点:

    1.nohup

    nohup命令可以在你退出帐户之后继续运行相应的进程。nohup就是不挂起的意思( no hang up)

    2.&

    当在前台运行某个作业时,终端被该作业占据;可以在命令后面加上& 实现后台运行

    一般情况下,两者同时使用:

    nohup command &

    ps all 可以查所有后台任务

    这样就不用管它了

    下载完成后的数据量如下

    image

    一般大型的文件的下载需要将其md5文件一起下载,来检验下载的文件是否下载完全

    
    md5sum KPGP-00001_L1_R1.fq.gz >md5tmp1.txt
    
    cat md5tmp1.tx
    
    cat KPGP-00001_L1_R1.fq.gz.md5
    
    

    如果结果一致就可以判断下载完全

    此时的目录应该如下:

    image

    Part2 测序reads的质控

    
    cat fastqc.sh
    
    #!/bin/bash
    
    for i in $(seq 1 6)
    
    do
    
    fastqc /home/ubuntu/WGS_new/input/KPGP-00001_L${i}_R1.fq.gz /home/ubuntu/WGS_new/input/KPGP-00001_L${i}_R2.fq.gz -o /home/ubuntu/WGS_new/output/fastqc_result && echo "KPGP-00001_L${i} fasqtc is done" >fastqc${i}.log
    
    done
    
    nohup bash fastqc.sh &
    

    由于测序数据有6个lane,而且又是pair-end测序,所以用到multiqc来归纳汇总。

    cd ~/WGS_new/output/fastqc_result
    multiqc *.zip 
    

    这一步之后产生的文件如下

    ├── input
    │   ├── KPGP-00001_L1_R1.fq.gz
    │   ├── KPGP-00001_L1_R2.fq.gz
    │   ├── KPGP-00001_L2_R1.fq.gz
    │   ├── KPGP-00001_L2_R2.fq.gz
    │   ├── KPGP-00001_L3_R1.fq.gz
    │   ├── KPGP-00001_L3_R2.fq.gz
    │   ├── KPGP-00001_L4_R1.fq.gz
    │   ├── KPGP-00001_L4_R2.fq.gz
    │   ├── KPGP-00001_L5_R1.fq.gz
    │   ├── KPGP-00001_L5_R2.fq.gz
    │   ├── KPGP-00001_L6_R1.fq.gz
    │   ├── KPGP-00001_L6_R2.fq.gz
    │   └── nohup.out
    ├── output
    │   └── fastqc_result
    │       ├── KPGP-00001_L1_R1_fastqc.html
    │       ├── KPGP-00001_L1_R1_fastqc.zip
    │       ├── KPGP-00001_L2_R1_fastqc.html
    │       ├── KPGP-00001_L2_R1_fastqc.zip
    │       ├── KPGP-00001_L2_R2_fastqc.html
    │       ├── KPGP-00001_L2_R2_fastqc.zip
    │       ├── KPGP-00001_L3_R1_fastqc.html
    │       ├── KPGP-00001_L3_R1_fastqc.zip
    │       ├── KPGP-00001_L3_R2_fastqc.html
    │       ├── KPGP-00001_L3_R2_fastqc.zip
    │       ├── KPGP-00001_L4_R1_fastqc.html
    │       ├── KPGP-00001_L4_R1_fastqc.zip
    │       ├── KPGP-00001_L4_R2_fastqc.html
    │       ├── KPGP-00001_L4_R2_fastqc.zip
    │       ├── KPGP-00001_L5_R1_fastqc.html
    │       ├── KPGP-00001_L5_R1_fastqc.zip
    │       ├── KPGP-00001_L5_R2_fastqc.html
    │       ├── KPGP-00001_L5_R2_fastqc.zip
    │       ├── KPGP-00001_L6_R1_fastqc.html
    │       ├── KPGP-00001_L6_R1_fastqc.zip
    │       ├── KPGP-00001_L6_R2_fastqc.html
    │       ├── KPGP-00001_L6_R2_fastqc.zip
    │       ├── multiqc_data
    │       │   ├── multiqc_data.json
    │       │   ├── multiqc_fastqc.txt
    │       │   ├── multiqc_general_stats.txt
    │       │   ├── multiqc.log
    │       │   └── multiqc_sources.txt
    │       └── multiqc_report.html
    └── script
        ├── fastqc1.log
        ├── fastqc2.log
        ├── fastqc3.log
        ├── fastqc4.log
        ├── fastqc5.log
        ├── fastqc6.log
        ├── fastqc.sh
        └── nohup.out
    
    

    此处的质量控制指的是原始数据的质量控制,接下来了解一下质控相关的知识
    (此处有借鉴微信公众号:解螺旋的矿工的文章)
    说到质量控制,先了解什么是质量值
    碱基质量值就是能够用来定量描述碱基好坏程度的一个数值。它该如何才能恰当地描述这个结果呢?我们试想一下,如果测序测得越准确,这个碱基的质量就应该越高;反之,测得越不准确,质量值就应该越低。也就是说可以利用碱基被测错的概率来描述它的质量值,错误率越低,质量值就越高。
    假定碱基的测序错误率为p_error,质量值为Q
    有公式:
    Q = -10log(p_error)
    如果该碱基的测序错误率是0.01,那么质量值就是20(俗称Q20),如果是0.001,那么质量值就是30(俗称Q30)。Q20和Q30的比例常常被我们用来评价某次测序结果的好坏,比例越高就越好。
    现在一般都是使用Phred33这个体系。
    基本上可以从下面几个方面来了解原始数据的质量值:
    1.reads各位置的碱基质量分布
    在做read质量值分析的时候,FastQC并不单独查看具体某一条read中碱基的质量值,而是将Fastq文件中所有的read数据都综合起来一起分析。如下图,来自KPGP-00001_L1_R1

    image.png
    这个图的横轴是read上碱基的位置,纵轴是碱基质量值。
    我们可以看到read上的每一个位置都有一个黄色的箱型图表示在该位置上所有碱基的质量分布情况。
    2.碱基总体质量值分布
    fastqc还会提供一个碱基总体的质量分布如下:
    image.png
    只要大部分都高于20,那么就比较正常
    另外,Q20和Q30的比例是我们衡量测序质量的一个重要指标。一般来说,对于二代测序,最好是达到Q20的碱基要在95%以上(最差不低于90%),Q30要求大于85%(最差也不要低于80%)
    3.reads各个位置上碱基比例分布
    image.png
    这个是为了分析碱基的分离程度。何为碱基分离?我们知道AT配对,CG配对,假如测序过程是比较随机的话(随机意味着好),那么在每个位置上A和T比例应该差不多,C和G的比例也应该差不多,如上图所示,两者之间即使有偏差也不应该太大,最好平均在1%以内,如果过高,除非有合理的原因,比如某些特定的捕获测序所致。
    4.GC含量分布图
    image.png
    GC含量指的是G和C这两中碱基占总碱基的比例。二代测序平台或多或少都存在一定的测序偏向性,我们可以通过查看这个值来协助判断测序过程是否足够随机。对于人类来说,我们基因组的GC含量一般在40%左右。因此,如果发现GC含量的图谱明显偏离这个值那么说明测序过程存在较高的序列偏向性,结果就是基因组中某些特定区域被反复测序的几率高于平均水平,除了覆盖度会有偏离之后,将会影响下游的变异检测和CNV分析。图中的GC含量约在39%,处于正常范围。
    5.N含量分布图
    image.png
    N在测序数据中一般是不应该出现的,如果出现则意味着,测序的光学信号无法被清晰分辨,如果这种情况多的话,往往意味着测序系统或者测序试剂的错误。图中接近0%。
    6.接头序列
    image.png
    在测序之前需要构建测序文库,测序接头就是在这个时候加上的,其目的一方面是为了能够结合到flowcell上,另一方面是当有多个样本同时测序的时候能够利用接头信息进行区分。当测序read的长度大于被测序的DNA片段时,就会在read的末尾测到这些接头序列。一般的WGS测序是不会测到这些接头序列的,因为构建WGS测序的文库序列(插入片段)都比较长,约几百bp,而read的测序长度都在100bp-150bp这个范围。不过在进行一些RNA测序的时候,由于它们的序列本来就比较短很多只有几十bp长(特别是miRNA),那么就很容易会出现read测通的现象,这个时候就会在read的末尾测到这些接头序列。
    image.png

    最后,如果测序质量很差的情况下,则需要切除测序接头序列和read的低质量序列
    工具有:SOAPnuke、cutadapt、untrimmed等,但是,常用的一般是SOAPnuke、cutadapt、untrimmed等。

    Part3 比对(mapping)

    step1

    mkdir /home/ubuntu/WGS_new/input/genome
    cd /home/ubuntu/WGS_new/input/genome
    wget  http://hgdownload.cse.ucsc.edu/goldenPath/hg38/bigZips/hg38.fa.gz 
    
    #对下载的基因组建立索引,下面是建索引的脚本
    #!/bin/bash
    bwa index -a bwtsw -p /home/ubuntu/WGS_new/input/genome/hg38 /home/ubuntu/WGS_new/input/genome/Homo_sapiens_assembly38.fasta && echo "bwa index of hg38 is done"
    
    #运行脚本
    nohup bash bwa_index.sh &
    

    索引构建完毕后的目录如下:

    ├── input
    │   ├── genome
    │   │   ├── hg38.amb
    │   │   ├── hg38.ann
    │   │   ├── hg38.bwt
    │   │   ├── hg38.fa
    │   │   ├── hg38.pac
    │   │   ├── hg38.sa
    │   │   └── nohup.out
    │   ├── KPGP-00001_L1_R1.fq.gz
    │   ├── KPGP-00001_L1_R2.fq.gz
    │   ├── KPGP-00001_L2_R1.fq.gz
    │   ├── KPGP-00001_L2_R2.fq.gz
    │   ├── KPGP-00001_L3_R1.fq.gz
    │   ├── KPGP-00001_L3_R2.fq.gz
    │   ├── KPGP-00001_L4_R1.fq.gz
    │   ├── KPGP-00001_L4_R2.fq.gz
    │   ├── KPGP-00001_L5_R1.fq.gz
    │   ├── KPGP-00001_L5_R2.fq.gz
    │   ├── KPGP-00001_L6_R1.fq.gz
    │   ├── KPGP-00001_L6_R2.fq.gz
    │   └── nohup.out
    ├── output
    │   └── fastqc_result
    │       ├── KPGP-00001_L1_R1_fastqc.html
    │       ├── KPGP-00001_L1_R1_fastqc.zip
    │       ├── KPGP-00001_L2_R1_fastqc.html
    │       ├── KPGP-00001_L2_R1_fastqc.zip
    │       ├── KPGP-00001_L2_R2_fastqc.html
    │       ├── KPGP-00001_L2_R2_fastqc.zip
    │       ├── KPGP-00001_L3_R1_fastqc.html
    │       ├── KPGP-00001_L3_R1_fastqc.zip
    │       ├── KPGP-00001_L3_R2_fastqc.html
    │       ├── KPGP-00001_L3_R2_fastqc.zip
    │       ├── KPGP-00001_L4_R1_fastqc.html
    │       ├── KPGP-00001_L4_R1_fastqc.zip
    │       ├── KPGP-00001_L4_R2_fastqc.html
    │       ├── KPGP-00001_L4_R2_fastqc.zip
    │       ├── KPGP-00001_L5_R1_fastqc.html
    │       ├── KPGP-00001_L5_R1_fastqc.zip
    │       ├── KPGP-00001_L5_R2_fastqc.html
    │       ├── KPGP-00001_L5_R2_fastqc.zip
    │       ├── KPGP-00001_L6_R1_fastqc.html
    │       ├── KPGP-00001_L6_R1_fastqc.zip
    │       ├── KPGP-00001_L6_R2_fastqc.html
    │       ├── KPGP-00001_L6_R2_fastqc.zip
    │       ├── multiqc_data
    │       │   ├── multiqc_data.json
    │       │   ├── multiqc_fastqc.txt
    │       │   ├── multiqc_general_stats.txt
    │       │   ├── multiqc.log
    │       │   └── multiqc_sources.txt
    │       └── multiqc_report.html
    └── script
        ├── bwa_index.sh
        ├── fastqc1.log
        ├── fastqc2.log
        ├── fastqc3.log
        ├── fastqc4.log
        ├── fastqc5.log
        ├── fastqc6.log
        ├── fastqc.sh
        └── nohup.out
    
    

    step2

    cd /home/ubuntu/WGS_new/output
    mkdir /home/ubuntu/WGS_new/output/bwa_mapping
    cd /home/ubuntu/WGS_new/script
    #比对的脚本如下
    #!/bin/bash     
    bwa mem -t 4 -R '@RG\tID:KPGP-00001_L1\tPL:illumina\tSM:KPGP-00001'  /home/ubuntu/WGS_new/input/genome/hg38 /home/ubuntu/WGS_new/input/KPGP-00001_L1_R1.fq.gz /home/ubuntu/WGS_new/input/KPGP-00001_L1_R2.fq.gz >/home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L1.sam && echo "KPGP-00001_L1 mapping is done" 
    bwa mem -t 4 -R '@RG\tID:KPGP-00001_L2\tPL:illumina\tSM:KPGP-00001'  /home/ubuntu/WGS_new/input/genome/hg38 /home/ubuntu/WGS_new/input/KPGP-00001_L2_R1.fq.gz /home/ubuntu/WGS_new/input/KPGP-00001_L2_R2.fq.gz >/home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L2.sam && echo "KPGP-00001_L2 mapping is done"
    bwa mem -t 4 -R '@RG\tID:KPGP-00001_L3\tPL:illumina\tSM:KPGP-00001'  /home/ubuntu/WGS_new/input/genome/hg38 /home/ubuntu/WGS_new/input/KPGP-00001_L3_R1.fq.gz /home/ubuntu/WGS_new/input/KPGP-00001_L3_R2.fq.gz >/home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L3.sam && echo "KPGP-00001_L3 mapping is done"
    bwa mem -t 4 -R '@RG\tID:KPGP-00001_L4\tPL:illumina\tSM:KPGP-00001'  /home/ubuntu/WGS_new/input/genome/hg38 /home/ubuntu/WGS_new/input/KPGP-00001_L4_R1.fq.gz /home/ubuntu/WGS_new/input/KPGP-00001_L4_R2.fq.gz >/home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L4.sam && echo "KPGP-00001_L4 mapping is done"
    bwa mem -t 4 -R '@RG\tID:KPGP-00001_L5\tPL:illumina\tSM:KPGP-00001'  /home/ubuntu/WGS_new/input/genome/hg38 /home/ubuntu/WGS_new/input/KPGP-00001_L5_R1.fq.gz /home/ubuntu/WGS_new/input/KPGP-00001_L5_R2.fq.gz >/home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L5.sam && echo "KPGP-00001_L5 mapping is done"
    bwa mem -t 4 -R '@RG\tID:KPGP-00001_L6\tPL:illumina\tSM:KPGP-00001'  /home/ubuntu/WGS_new/input/genome/hg38 /home/ubuntu/WGS_new/input/KPGP-00001_L6_R1.fq.gz /home/ubuntu/WGS_new/input/KPGP-00001_L6_R2.fq.gz >/home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L6.sam && echo "KPGP-00001_L6 mapping is done"
    
    #运行脚本
    nohup bash bwa_mapping.sh &
    

    比对后生成sam文件,将sam文件转换成二进制格式的bam文件

    #转换的脚本如下
    #!/bin/bash
    for i in $(seq 1 6)
    do
    samtools view -Sb /home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L${i}.sam >/home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L${i}.bam && echo "KPGP-00001_L${i} samt2bam is done"
    done
    
    #运行脚本
    nohup bash sam2bam.sh &
    
    #运行结束后,再把sam格式文件删除,其实可以不删除,但是太占储存空间了
    cd /home/ubuntu/WGS_new/output/bwa_mapping
    rm *.sam
    

    结果如下:

    ├── input
    │   ├── genome
    │   │   ├── hg38.amb
    │   │   ├── hg38.ann
    │   │   ├── hg38.bwt
    │   │   ├── hg38.fa
    │   │   ├── hg38.pac
    │   │   ├── hg38.sa
    │   │   └── nohup.out
    │   ├── KPGP-00001_L1_R1.fq.gz
    │   ├── KPGP-00001_L1_R2.fq.gz
    │   ├── KPGP-00001_L2_R1.fq.gz
    │   ├── KPGP-00001_L2_R2.fq.gz
    │   ├── KPGP-00001_L3_R1.fq.gz
    │   ├── KPGP-00001_L3_R2.fq.gz
    │   ├── KPGP-00001_L4_R1.fq.gz
    │   ├── KPGP-00001_L4_R2.fq.gz
    │   ├── KPGP-00001_L5_R1.fq.gz
    │   ├── KPGP-00001_L5_R2.fq.gz
    │   ├── KPGP-00001_L6_R1.fq.gz
    │   ├── KPGP-00001_L6_R2.fq.gz
    │   └── nohup.out
    ├── output
    │   ├── bwa_mapping
    │   │   ├── KPGP-00001_L1.bam
    │   │   ├── KPGP-00001_L2.bam
    │   │   ├── KPGP-00001_L3.bam
    │   │   ├── KPGP-00001_L4.bam
    │   │   ├── KPGP-00001_L5.bam
    │   │   └── KPGP-00001_L6.bam
    │   └── fastqc_result
    │       ├── KPGP-00001_L1_R1_fastqc.html
    │       ├── KPGP-00001_L1_R1_fastqc.zip
    │       ├── KPGP-00001_L2_R1_fastqc.html
    │       ├── KPGP-00001_L2_R1_fastqc.zip
    │       ├── KPGP-00001_L2_R2_fastqc.html
    │       ├── KPGP-00001_L2_R2_fastqc.zip
    │       ├── KPGP-00001_L3_R1_fastqc.html
    │       ├── KPGP-00001_L3_R1_fastqc.zip
    │       ├── KPGP-00001_L3_R2_fastqc.html
    │       ├── KPGP-00001_L3_R2_fastqc.zip
    │       ├── KPGP-00001_L4_R1_fastqc.html
    │       ├── KPGP-00001_L4_R1_fastqc.zip
    │       ├── KPGP-00001_L4_R2_fastqc.html
    │       ├── KPGP-00001_L4_R2_fastqc.zip
    │       ├── KPGP-00001_L5_R1_fastqc.html
    │       ├── KPGP-00001_L5_R1_fastqc.zip
    │       ├── KPGP-00001_L5_R2_fastqc.html
    │       ├── KPGP-00001_L5_R2_fastqc.zip
    │       ├── KPGP-00001_L6_R1_fastqc.html
    │       ├── KPGP-00001_L6_R1_fastqc.zip
    │       ├── KPGP-00001_L6_R2_fastqc.html
    │       ├── KPGP-00001_L6_R2_fastqc.zip
    │       ├── multiqc_data
    │       │   ├── multiqc_data.json
    │       │   ├── multiqc_fastqc.txt
    │       │   ├── multiqc_general_stats.txt
    │       │   ├── multiqc.log
    │       │   └── multiqc_sources.txt
    │       └── multiqc_report.html
    └── script
        ├── bwa_index.sh
        ├── bwa_mapping.sh
        ├── fastqc1.log
        ├── fastqc2.log
        ├── fastqc3.log
        ├── fastqc4.log
        ├── fastqc5.log
        ├── fastqc6.log
        ├── fastqc.sh
        ├── nohup.out
        └── sam2bam.sh
    
    

    step3
    对生成的bam文件按position排序

    #脚本如下
    
    #!/bin/bash
    for i in $(seq 1 6)
    do
    samtools sort -@ 4 -m 4G -O bam -o /home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L${i}.sorted.bam /home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L${i}.bam && echo "/KPGP-00001_L${i}.sorted.bam is done"
    done
    

    此时所有结果如下

    ├── input
    │     ├── genome
    │   │   ├── hg38.amb
    │?? │?? ├── hg38.ann
    │?? │?? ├── hg38.bwt
    │?? │?? ├── hg38.fa
    │?? │?? ├── hg38.pac
    │?? │?? ├── hg38.sa
    │?? │?? └── nohup.out
    │?? ├── KPGP-00001_L1_R1.fq.gz
    │?? ├── KPGP-00001_L1_R2.fq.gz
    │?? ├── KPGP-00001_L2_R1.fq.gz
    │?? ├── KPGP-00001_L2_R2.fq.gz
    │?? ├── KPGP-00001_L3_R1.fq.gz
    │?? ├── KPGP-00001_L3_R2.fq.gz
    │?? ├── KPGP-00001_L4_R1.fq.gz
    │?? ├── KPGP-00001_L4_R2.fq.gz
    │?? ├── KPGP-00001_L5_R1.fq.gz
    │?? ├── KPGP-00001_L5_R2.fq.gz
    │?? ├── KPGP-00001_L6_R1.fq.gz
    │?? ├── KPGP-00001_L6_R2.fq.gz
    │?? └── nohup.out
    ├── output
    │?? ├── bwa_mapping
    │?? │?? ├── index
    │?? │?? ├── KPGP-00001_L1.bam
    │?? │?? ├── KPGP-00001_L1.sorted.bam
    │?? │?? ├── KPGP-00001_L2.bam
    │?? │?? ├── KPGP-00001_L2.sorted.bam
    │?? │?? ├── KPGP-00001_L3.bam
    │?? │?? ├── KPGP-00001_L3.sorted.bam
    │?? │?? ├── KPGP-00001_L4.bam
    │?? │?? ├── KPGP-00001_L4.sorted.bam
    │?? │?? ├── KPGP-00001_L5.bam
    │?? │?? ├── KPGP-00001_L5.sorted.bam
    │?? │?? ├── KPGP-00001_L6.bam
    │?? │?? └── KPGP-00001_L6.sorted.bam
    │?? └── fastqc_result
    │??     ├── KPGP-00001_L1_R1_fastqc.html
    │??     ├── KPGP-00001_L1_R1_fastqc.zip
    │??     ├── KPGP-00001_L2_R1_fastqc.html
    │??     ├── KPGP-00001_L2_R1_fastqc.zip
    │??     ├── KPGP-00001_L2_R2_fastqc.html
    │??     ├── KPGP-00001_L2_R2_fastqc.zip
    │??     ├── KPGP-00001_L3_R1_fastqc.html
    │??     ├── KPGP-00001_L3_R1_fastqc.zip
    │??     ├── KPGP-00001_L3_R2_fastqc.html
    │??     ├── KPGP-00001_L3_R2_fastqc.zip
    │??     ├── KPGP-00001_L4_R1_fastqc.html
    │??     ├── KPGP-00001_L4_R1_fastqc.zip
    │??     ├── KPGP-00001_L4_R2_fastqc.html
    │??     ├── KPGP-00001_L4_R2_fastqc.zip
    │??     ├── KPGP-00001_L5_R1_fastqc.html
    │??     ├── KPGP-00001_L5_R1_fastqc.zip
    │??     ├── KPGP-00001_L5_R2_fastqc.html
    │??     ├── KPGP-00001_L5_R2_fastqc.zip
    │??     ├── KPGP-00001_L6_R1_fastqc.html
    │??     ├── KPGP-00001_L6_R1_fastqc.zip
    │??     ├── KPGP-00001_L6_R2_fastqc.html
    │??     ├── KPGP-00001_L6_R2_fastqc.zip
    │??     ├── multiqc_data
    │??     │?? ├── multiqc_data.json
    │??     │?? ├── multiqc_fastqc.txt
    │??     │?? ├── multiqc_general_stats.txt
    │??     │?? ├── multiqc.log
    │??     │?? └── multiqc_sources.txt
    │??     └── multiqc_report.html
    └── script
        ├── bam_index.sh
        ├── bwa_index.sh
        ├── bwa_mapping.sh
        ├── fastqc1.log
        ├── fastqc2.log
        ├── fastqc3.log
        ├── fastqc4.log
        ├── fastqc5.log
        ├── fastqc6.log
        ├── fastqc.sh
        ├── nohup.out
        └── sam2bam.sh
    

    以上的步骤就完成了比对的过程
    在此基础上,做一些以下的横向探索:

    1.分别利用 samtools和 bedtools 对测序深度和覆盖度进行统计,并可视化
    
    2.把bam文件按染色体分成小文件,并用IGV查看
    
    3.bam格式转化为bw格式看测序深度分布
    
    4.测序深度和GC含量的关系
    
    

    1.分别利用 samtools和 bedtools 对测序深度和覆盖度进行统计,并可视化

    用samtools 对测序深度进行统计

    #!/bin/bash
    for i in $(seq 1 6)
    do
    samtools depth /home/ubuntu/WGS_new/output/bwa_mapping/KPGP-00001_L${i}.sorted.bam 1>/home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L${i}.sorted.bam.depth 2>&1 && echo "KPGP-00001_L${i}.sorted.bam depth count is done"
    done
    

    这个软件得到的文件格式如下

    chr1    9999    4
    chr1    10000   5
    chr1    10001   51
    chr1    10002   161
    chr1    10003   250
    chr1    10004   278
    chr1    10005   365
    chr1    10006   390
    chr1    10007   391
    chr1    10008   397
    chr1    10009   406
    chr1    10010   407
    chr1    10011   414
    chr1    10012   415
    chr1    10013   417
    chr1    10014   420
    chr1    10015   420
    chr1    10016   419
    chr1    10017   421
    chr1    10018   422
    chr1    10019   425
    chr1    10020   427
    chr1    10021   430
    chr1    10022   432
    chr1    10023   435
    chr1    10024   435
    chr1    10025   437
    chr1    10026   439
    chr1    10027   439
    chr1    10028   440
    chr1    10029   440
    chr1    10030   442
    ...
    ...
    

    第一列是染色体号,第二列是对应的单个碱基位置,第三列是单个碱基的深度

    需要进一步统计到每个染色体对应的测序深度

    这一步的python脚本如下

    import sys
    args=sys.argv
    filename=args[1]
    SumDict={}
    for line in open(filename):
      lineL=line.strip().split("\t")
      ID=lineL[0]
      depth=int(lineL[2])
      if ID not in SumDict:
         SumDict[ID]=depth
      else:
         SumDict[ID]+=depth
    for k,v in SumDict.items():
       print(k,v,sep="\t")
    
    -----------------------------
    nohup time python3 sumDepth.py /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L1.sorted.bam.depth > /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L1.SumOfDepth.txt &
    
    nohup time python3 sumDepth.py /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L2.sorted.bam.depth > /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L2.SumOfDepth.txt &
    
    nohup time python3 sumDepth.py /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L3.sorted.bam.depth > /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L3.SumOfDepth.txt &
    
    nohup time python3 sumDepth.py /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L4.sorted.bam.depth > /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L4.SumOfDepth.txt &
    
    nohup time python3 sumDepth.py /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L5.sorted.bam.depth > /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L5.SumOfDepth.txt &
    
    nohup time python3 sumDepth.py /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L6.sorted.bam.depth > /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L6.SumOfDepth.txt &
    

    得到的统计结果还需要把带“_”部分除掉

    #!/bin/bash
    for i in $(seq 1 6)
    do
    grep -v "_" /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L${i}.SumOfDepth.txt >/home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L${i}.SumOfDepth.final.txt
    done
    

    然后将所有的生成文件排序后合并,脚本如下

    cd /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth
    
    #脚本
    --------
    #!/bin/bash
    for i in $(seq 1 6)
    do
    sed -i "s/chr//" KPGP-00001_L${i}.SumOfDepth.final.txt #首次去掉chr,方便排序
    sort -k1,1n KPGP-00001_L${i}.SumOfDepth.final.txt > KPGP-00001_L${i}.SumOfDepth.sort.final.txt  #对第一列按数值排序
    sed -i 's/^/chr/' KPGP-00001_L${i}.SumOfDepth.sort.final.txt  #再将chr添加回来
    
    done
    
    
    paste KPGP-00001_L*.SumOfDepth.sort.final.txt >KPGP-00001_all.SumOfDepth.sort.final.txt
    
    awk '{sum=$2+$$4+$6+$8+$10+$12;print $1,sum;}' KPGP-00001_all.SumOfDepth.sort.final.txt >KPGP-00001.SumOfDepth.final_count.txt
    ---------
    #运行脚本
    nohup bash paste_sort.sh &
    
    -----------
    sed -i '1 i Chrom\tsum_of_depth' KPGP-00001.SumOfDepth.final_count.txt
    cat KPGP-00001.SumOfDepth.final_count.txt
    -----------
    Chrom   sum_of_depth
    chrM 34591025
    chrX 4093132439
    chrY 125469175
    chr1 6482954037
    chr2 6376037101
    chr3 5286606057
    chr4 5330867456
    chr5 4949134249
    chr6 4420827669
    chr7 4173524521
    chr8 3842370943
    chr9 3228529809
    chr10 3626998764
    chr11 3548159595
    chr12 3490214776
    chr13 2618593673
    chr14 2359781279
    chr15 2098133774
    chr16 2341297030
    chr17 1911455487
    chr18 2082861061
    chr19 1341657686
    chr20 1741460772
    chr21 1203547746
    chr22 988334122
    
    sed -i 's/ /\t/' KPGP-00001.SumOfDepth.final_count.txt
    
    
    

    以上就将所有的染色体的覆盖位点的测序深度总和统计出来了

    接下来计算覆盖度

    因为samtools depth计算的是所有覆盖的每个碱基的深度,所以将对应染色体的统计信息提取,并计算有多少个碱基,得到的碱基数就是对应的覆盖长度。
    所以有如下脚本统计

    #!/bin/bash
    for i in $(seq 1 22) 
    do
    grep "chr${i}   " /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L1.sorted.bam.depth |wc -l >/home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chr${i}_cov.txt
    sed -i "1 i chr${i}" /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chr${i}_cov.txt
    done
    
    grep "chrX  " /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L1.sorted.bam.depth |wc -l >/home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chrX_cov.txt #x染色体
    sed -i "1 i chrX" /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chrX_cov.txt
    
    grep "chrY  " /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L1.sorted.bam.depth |wc -l >/home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chrY_cov.txt #y染色体
    sed -i "1 i chrY" /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chrY_cov.txt
    
    grep "chrM  " /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L1.sorted.bam.depth |wc -l >/home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chrM_cov.txt #线粒体
    sed -i "1 i chrM" /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chrM_cov.txt
    

    这里计算的是一个lane的coverage,应该要计算所有6个lane的coverage,再求mean值,或者提前将6个lane的bam文件merge后再处理。此处由于系统存储空间问题,只对一个lane作简单统计。

    sort -m chr*_cov.txt|sed -n 1~2p> chr_cov1.txt
    sort -m chr*_cov.txt|sed -n 2~2p> chr_cov2.txt
    paste chr_cov*.txt>chr_cov_all.txt
    sed 's/chr//' chr_cov_all.txt|sort -k1,1n|sed 's/^/chr/'|sed '1 i Chrom\tcoverage' >chr_cov.txt
    cat chr_cov.txt
    
    
    Chrom   coverage
    chrM    16569
    chrX    151545600
    chrY    4004642
    chr1    224300366
    chr2    235466712
    chr3    194391189
    chr4    185704231
    chr5    176555626
    chr6    164731880
    chr7    155128428
    chr8    141501464
    chr9    118343356
    chr10   129732215
    chr11   131193733
    chr12   130177621
    chr13   95749291
    chr14   87847379
    chr15   81867181
    chr16   78578328
    chr17   78271424
    chr18   77398752
    chr19   54075815
    chr20   62148856
    chr21   38164294
    chr22   36926516
    
    
    

    计算参考序列染色体的长度
    这里首先需要将hg38中的重复的N序列去除
    首先想到的是

    grep -v "N" hg38.fa >hg38.cut.fa
    

    这里有一个小问题,就是如果N藏在正常ATGC序列之中的话,就很容易去除掉正常的碱基
    所以改成sed命令

    sed 's/N//g' hg38.fa >hg38.sed.fa #把所有的N替换成空
    sed '/^$/d' hg38.sed.fa >hg38.final.fa  #去除空行
    
    

    sed是将N替换成空,并不是将含N的行除去
    虽然两个命令得到结果一样,但还是选择后者是正确的。

    写了2个python脚本分别统计1.hg38原始文件对应各条染色体的长度
    2.hg38去除N之后的各条染色体的长度
    3.hg38原始文件的各条染色体的N含量
    脚本如下

    import sys
    args=sys.argv
    filename=args[1]
    seq_id={}
    
    for line in open(filename):
      line=line.strip()
      if line.startswith(">"):
          seq_name = line
          if seq_name not in seq_id:
              seq_id[seq_name]=''
      else:
          seq_id[seq_name]+=line.strip()
    for k,v in seq_id.items():
       seq_length=len(v)
       name=k[1:]
       print(name,seq_length,sep="\t")
    ---------------------------------------------------
    #运行脚本
    --------------------
    nohup python3 count_length.py hg38.fa > hg38.chr_length.txt &
    nohup python3 count_length.py hg38.final.fa > hg38.cutN.chr_length.txt &
    -----------------------------------
    import sys
    args=sys.argv
    filename=args[1]
    seq_id={}
    
    for line in open(filename):
      line=line.strip()
      if line.startswith(">"):
          seq_name = line
          if seq_name not in seq_id:
              seq_id[seq_name]=''
      else:
          seq_id[seq_name]+=line
    for k,v in seq_id.items():
       N_count=v.count("N")
       name=k[1:]
       print(k,N_count,sep="\t")
    --------------------------
    #运行脚本
    nohup python3 count_N.py hg38.fa >hg38.chr.countN.txt &
    

    这两个脚本本身没有问题,而且对于fasta格式读取,把ID 和序列先构建字典的方式也是之前总结出来的
    但是!!!!
    对于大型的文件,先构建字典,在读取字典的过程会花费太多的时间,所以这两个脚本运行了如下的时间,程序还没有跑完

    image.png

    所以,需要修改代码,不要用这种构建字典的方式。
    修改后的脚本如下:

    #统计长度的脚本
    
    import sys
    args=sys.argv
    filename=args[1]
    seq_length=0
    for line in open(filename):
      line=line.strip()
      if line.startswith(">"):
         if seq_length:
            print(seq_length) 
         seq_length=0
         print(line)
      else:
         seq_length+=len(line)
    print(seq_length)
    --------------------------------------
    #统计N数量的脚本
    import sys
    args=sys.argv
    filename=args[1]
    num_N=0
    for line in open(filename):
      line=line.strip()
      if line.startswith(">"):
         if num_N :
           print (num_N)  
         num_N=0
         print (line)
    
      else:
          num_N+=line.count("N")
    
    print(num_N)
    -----------
    

    优化后的代码只花了2到3分钟就完成任务,可见代码优化的重要性。

    因为得到结果不仅仅有chr1~22+x+y+M的信息,还有其他信息,所以需要提取
    提取脚本如下

    #!/bin/bash
    for i in $(seq 1 22)
    do
    grep -A 1 ">chr${i}$" hg38.cutN.chr_length.txt > hg38.cutN.chr_length.final${i}.txt
    grep -A 1 ">chr${i}$" count_N_new.txt > count_N_new.final${i}.txt
    done
    #!/bin/bash
    for i in $(seq 1 22)
    do
    grep -A 1 ">chr${i}$" hg38.chr_length.txt >hg38.chr_length.final${i}.txt        #提取>chr${i}$以及其下面一行,-A是after的意思,之所以是chr${i}+一个$是因为chr${i}后面加空行
    才是想要的结果,如果不清楚可以cat -A 一下,再判断
    grep -A 1 ">chr${i}$" hg38.cutN.chr_length.txt > hg38.cutN.chr_length.final${i}.txt
    grep -A 1 ">chr${i}$" count_N_new.txt > count_N_new.final${i}.txt
    done
    
    grep -A 1 ">chrX$" hg38.chr_length.txt >hg38.chr_length.finalX.txt
    grep -A 1 ">chrX$" hg38.cutN.chr_length.txt > hg38.cutN.chr_length.finalX.txt
    grep -A 1 ">chrX$" count_N_new.txt > count_N_new.finalX.txt
    
    grep -A 1 ">chrY$" hg38.chr_length.txt >hg38.chr_length.finalY.txt
    grep -A 1 ">chrY$" hg38.cutN.chr_length.txt > hg38.cutN.chr_length.finalY.txt
    grep -A 1 ">chrY$" count_N_new.txt > count_N_new.finalY.txt
    
    grep -A 1 ">chrM$" hg38.chr_length.txt >hg38.chr_length.finalM.txt
    grep -A 1 ">chrM$" hg38.cutN.chr_length.txt > hg38.cutN.chr_length.finalM.txt
    grep -A 1 ">chrM$" count_N_new.txt > count_N_new.finalM.txt
    
    rm hg38.chr_length.txt
    rm hg38.cutN.chr_length.txt
    rm count_N_new.txt
    
    sort -m  hg38.chr_length.final*.txt >hg38.chr_length.final_all.txt   #将所有hg38.chr_length.final*.txt 文件合并,区别于paste,这个合并成列
    sort -m  hg38.cutN.chr_length.final*.txt >hg38.cutN.chr_length.final_all.txt
    sort -m  count_N_new.final*.txt >count_N_new.final_all.txt
    
    sed -n 1~2p hg38.chr_length.final_all.txt >hg38.chr_length.final_all_1.txt    #提取奇数行,1~2p中1是第一行,2p是从第一行开始,每2行输出,也就是输出奇数行
    sed -n 2~2p hg38.chr_length.final_all.txt >hg38.chr_length.final_all_2.txt    #提取偶数行,2~2p中1是第一行,2p是从第一行开始,每2行输出,也就是输出偶数行
    paste hg38.chr_length.final_all_1.txt hg38.chr_length.final_all_2.txt > hg38.chr_length.final_all_3.txt #hg38每条染色体的长度,包括N
    

    这里包括3个知识点:

    1. grep -A 1 string file 提取file中匹配到string的行和下面一行,1可以改成其他数字,表示多行
      grep -B 1 string file 上面
      grep -C 1 string file 上面和下面

    2.cat -A 之后再找匹配的字符串比较准确

    1. sort -m 将文件合并成列,区别与paste
    2. sed -n 1~2p 提取奇数行
      sed -n 2~2p 提取偶数行
      当然awk也很容易实现

    上面提取之后的文件排序,加列标题,然后合并
    脚本如下:

     sed 's/>chr//' count_N_new.final_all_3.txt |sort -k1,1n |sed 's/^/chr/'|sed '1 i Chrom\tN_Number' >N_number.txt   #排序,然后添加列标题
    
    sed 's/>chr//' hg38.cutN.chr_length.final_all_3.txt |sort -k1,1n |sed 's/^/chr/'|sed '1 i Chrom\tCut_N_length' >hg38.cutN.len.txt
    
    sed 's/>chr//' hg38.chr_length.final_all_3.txt |sort -k1,1n |sed 's/^/chr/'|sed '1 i Chrom\tlength' >hg38.len.txt
    paste hg38.len.txt hg38.cutN.len.txt N_number.txt |cut -f 1,2,4,6 >hg38.count_all_final.txt
    
    less -S hg38.count_all_final.txt
    -------------------------------------------------
    Chrom   length  Cut_N_length    N_Number
    chrM    16569   16568   1
    chrX    156040895       154893130       1147765
    chrY    57227415        26415183        30812232
    chr1    248956422       230481193       18475229
    chr2    242193529       240548238       1645291
    chr3    198295559       198100139       195420
    chr4    190214555       189752667       461888
    chr5    181538259       181265378       272881
    chr6    170805979       170078724       727255
    chr7    159345973       158970132       375841
    chr8    145138636       144768136       370500
    chr9    138394717       121790590       16604127
    chr10   133797422       133263135       534287
    chr11   135086622       134533742       552880
    chr12   133275309       133138039       137270
    chr13   114364328       97983128        16381200
    chr14   107043718       90568149        16475569
    chr15   101991189       84641348        17349841
    chr16   90338345        81805944        8532401
    chr17   83257441        82921074        336367
    chr18   80373285        80089658        283627
    chr19   58617616        58440758        176858
    chr20   64444167        63944581        499586
    chr21   46709983        40088683        6621300
    chr22   50818468        39159777        11658691
    
    --------------
    结果一目了然
    
    -------------------------------------------------------------------------------
    

    最后再把测序深度、覆盖度、参考序列长度合并

    cd /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/new
    ls -lh
    ------
    total 12K
    -rw-rw-r-- 1 ubuntu ubuntu 387 Aug  7 22:11 chr_cov.txt
    -rw-rw-r-- 1 ubuntu ubuntu 834 Aug  7 21:51 hg38.count_all_final.txt
    -rw-rw-r-- 1 ubuntu ubuntu 429 Aug  7 22:18 KPGP-00001.SumOfDepth.final_count.txt
    -------
    paste * |cut -f 1,2,4,5,6,8 >count_all.txt
    cat count_all.txt
    
    Chrom   coverage    length  Cut_N_length    N_Number    sum_of_depth
    chrM    16569   16569   16568   1   34591025
    chrX    151545600   156040895   154893130   1147765 4093132439
    chrY    4004642 57227415    26415183    30812232    125469175
    chr1    224300366   248956422   230481193   18475229    6482954037
    chr2    235466712   242193529   240548238   1645291 6376037101
    chr3    194391189   198295559   198100139   195420  5286606057
    chr4    185704231   190214555   189752667   461888  5330867456
    chr5    176555626   181538259   181265378   272881  4949134249
    chr6    164731880   170805979   170078724   727255  4420827669
    chr7    155128428   159345973   158970132   375841  4173524521
    chr8    141501464   145138636   144768136   370500  3842370943
    chr9    118343356   138394717   121790590   16604127    3228529809
    chr10   129732215   133797422   133263135   534287  3626998764
    chr11   131193733   135086622   134533742   552880  3548159595
    chr12   130177621   133275309   133138039   137270  3490214776
    chr13   95749291    114364328   97983128    16381200    2618593673
    chr14   87847379    107043718   90568149    16475569    2359781279
    chr15   81867181    101991189   84641348    17349841    2098133774
    chr16   78578328    90338345    81805944    8532401 2341297030
    chr17   78271424    83257441    82921074    336367  1911455487
    chr18   77398752    80373285    80089658    283627  2082861061
    chr19   54075815    58617616    58440758    176858  1341657686
    chr20   62148856    64444167    63944581    499586  1741460772
    chr21   38164294    46709983    40088683    6621300 1203547746
    chr22   36926516    50818468    39159777    11658691    988334122
    
    
    awk 'BEGIN{OFS=FS="\t";}{if (NR>1){cov=$2/$4;print cov}}' count_all.txt >cov_percent.txt #计算覆盖率
    awk 'BEGIN{OFS=FS="\t";}{if (NR>1){cov=$6/$2;print cov}}' count_all.txt >mean_depth.txt
    sed -i '1 i cov_percent' cov_percent.txt
    paste count_all.txt mean_depth.txt cov_percent.txt >count_all_done.txt
    cat count_all_done.txt
    
    Chrom   coverage    length  Cut_N_length    N_Number    sum_of_depth    mean_depth  cov_percent
    chrM    16569   16569   16568   1   34591025    2087.7  1.00006
    chrX    151545600   156040895   154893130   1147765 4093132439  27.0092 0.978388
    chrY    4004642 57227415    26415183    30812232    125469175   31.3309 0.151604
    chr1    224300366   248956422   230481193   18475229    6482954037  28.903  0.973183
    chr2    235466712   242193529   240548238   1645291 6376037101  27.0783 0.978875
    chr3    194391189   198295559   198100139   195420  5286606057  27.1957 0.981277
    chr4    185704231   190214555   189752667   461888  5330867456  28.7062 0.978665
    chr5    176555626   181538259   181265378   272881  4949134249  28.0316 0.974017
    chr6    164731880   170805979   170078724   727255  4420827669  26.8365 0.968563
    chr7    155128428   159345973   158970132   375841  4173524521  26.9037 0.975834
    chr8    141501464   145138636   144768136   370500  3842370943  27.1543 0.977435
    chr9    118343356   138394717   121790590   16604127    3228529809  27.281  0.971695
    chr10   129732215   133797422   133263135   534287  3626998764  27.9576 0.973504
    chr11   131193733   135086622   134533742   552880  3548159595  27.0452 0.975173
    chr12   130177621   133275309   133138039   137270  3490214776  26.8112 0.977764
    chr13   95749291    114364328   97983128    16381200    2618593673  27.3484 0.977202
    chr14   87847379    107043718   90568149    16475569    2359781279  26.8623 0.969959
    chr15   81867181    101991189   84641348    17349841    2098133774  25.6285 0.967224
    chr16   78578328    90338345    81805944    8532401 2341297030  29.7957 0.960545
    chr17   78271424    83257441    82921074    336367  1911455487  24.4209 0.943927
    chr18   77398752    80373285    80089658    283627  2082861061  26.9108 0.966401
    chr19   54075815    58617616    58440758    176858  1341657686  24.8107 0.92531
    chr20   62148856    64444167    63944581    499586  1741460772  28.0208 0.971917
    chr21   38164294    46709983    40088683    6621300 1203547746  31.536  0.951997
    chr22   36926516    50818468    39159777    11658691    988334122   26.7649 0.942971
    
    
    

    知识补充:
    1depth 测序深度
    测序深度是指测序得到的总碱基数与待测基因组大小的比值,可以理解为基因组中每个碱基被测序到的平均次数。测序深度 = reads长度 × 比对的reads数目 / 参考序列长度。假设一个基因大小为2M,测序深度为10X,那么获得的总数据量为20M。
    之所以测序深度=reads长度×比对的reads数目 / 参考序列长度,可以这么去理解,因为深度指的是每个碱基被测序到的平均次数。所以假设reads长度特别长,长到等于参考序列长度(当然这不可能)。那么,这时候reads数目就直接等于测序深度,但是reads长度远远没有参考序列长,所以才有了相当于reads长度/参考序列长度,这样的一个可以理解为矫正系数。

    如果我们的研究目的仅仅是进行群体遗传分析等类型的分析。由于分析是通过计算基因组不同区域的多样性变化来推断进化选择压力,或构建进化树推断遗传分化关系,SNP检出率达到70~90%足以达到此类目的。所以,此类研究常见的测序深度选择在10X左右。

    如果想检测个体的全基因组突变,来寻找某个特定功能突变,则我们推荐大于30X的测序深度,以保证接近于“毫无疏漏”。

    如果测序样本是混样,例如,癌组织样本(癌细胞的细胞异质性很大),BSA分析中的群体混合池样本。那么在保证30X的测序深度的基础上,如果经费许可50X的测序深度更佳,以保证对混合池中低频变异的检测成功率(例如,新出现或即将消亡的癌细胞突变)。

    2.coverage 覆盖度:
    覆盖度是指测序获得的序列占整个基因组的比例。指的是基因组上至少被检测到1次的区域,占整个基因组的比例。当然,有些文章中也会将测序深度称为Coverage,容易给我们带来混淆。因此,我们还是需要根据语境来推断Coverage的意思。
    我们假设基因组大小为G, 假定每次测序可从基因组任何位置上随机检测一个碱基。那么对于基因组上某一个固定碱基位置,在一次测序中,该位置被命中的概率为P (P=1/G)。我们将试验重复n次,相当于产生了n个碱基(n=c*G, c为测序深度)。 碱基的深度分布,相当于求该位置被测到0次,1次,…,n次的概率各是多少? 位点被检测到的n次的概率符合泊松分布。当然,由于概率极低,检测次数很大,所以这样的泊松分布接近于正态分布。

    由于基因组中的高GC、重复序列等复杂结构的存在,测序最终拼接组装获得的序列往往无法覆盖有所的区域,这部分没有获得的区域就称为Gap。例如一个细菌基因组测序,覆盖度是98%,那么还有2%的序列区域是没有通过测序获得的。

    上面统计所有染色体测序深度用的是python的脚本,这里也提供一个shell脚本,但是代码会相对长一点。

    #!/bin/bash
    for i in $(seq 1 22) #22对染色体
    do
    grep "chr${i}   " /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L1.sorted.bam.depth |cut -f 3 |awk '{sum += $1;}END{print sum;}' >/home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chr${i}.txt #注意END 的使用 |注意\t键的使用,脚本中可以直接键入tab,命令行下先Ctrl+V,再按tab键。这里之所以要加tab键,是因为,比如,如果>不加tab键,grep "chr1" 得到包括chr1,chr11,chr1_...>等。
    
    sed -i "1 i chr${i}" /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chr${i}.txt # 1表示第一行,i表示插入,即在第一行前面插入新行,名称为chr${i}
    done
    
    grep "chrX      " /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L1.sorted.bam.depth |cut -f 3 |awk '{sum += $1;}END{print sum;}' > /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chrx.txt #x染色体
    grep "chrY      " /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/KPGP-00001_L1.sorted.bam.depth |cut -f 3 |awk '{sum += $1;}END{print sum;}' > /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chry.txt #y染色体
    sed -i "1 i chrx" /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chrx.txt #添加列标题 chrx
    sed -i "1 i chry" /home/ubuntu/WGS_new/output/bwa_mapping/samtools_depth/chry.txt
    

    注意:awk命令要注意尽量冒号小写

    awk '{sum += $1} END{print sum}' chr2.tmp
    结果
    3399
    而
    awk "{sum += $1} END{print sum}" chr2.tmp
    报错
    awk: cmd. line:1: {sum += } END{print sum}
    awk: cmd. line:1:         ^ syntax error
    

    小总结

    cut -f 可以提取特定列
    cut -f 2 提取第2列
    sed -n 2p 提取2行
    sed -n 2,4p 提取2至3行
    

    对于上诉得到的汇总结果存到count.txt中,并进行可视化,脚本如下

    
    pdf()
    library(ggplot2)
    data <- read.table("count.txt",header = T)
    #因为上一个命令,header=T已经将首行作为列标题,所以$1没法识别,用$加列名
    data <-data[-1,] #将线粒体那行删除
    data$Chrom <-factor(data$Chrom,levels = c(1:22,"X","Y")) #这一步很重要,这样横坐标就按顺序排列了
    Chr <- data$Chrom
    M <- data$mean_depth
    C <- data$cov_percent
    dt1 <- data.frame(Chr,M)
    
    
    dt2 <- data.frame(Chr,C)
    
    p1 <- ggplot(dt1,aes(x=Chr,y=M))+xlab("chrom ID")+ylab("mean_depth")+labs(title="KPGP-00001")+ylim(0,100)+geom_bar(aes(fill=Chr),stat = "identity")+theme_bw()+theme(plot.title = element_text(hjust = 0.5),panel.grid.major =element_blank(),panel.grid.minor = element_blank())
    
    # 1    ggplot(dt1,aes(x=Chr,y=M,group=Chr))是构建一个画板
    # 2    +xlab("chrom ID")+ylab("mean_depth") 是更改横纵坐标标签
    # 3    +labs(title="KPGP-00001") 是增加主标题
    # 4    ylim(0,100) 设置y轴刻度为1~100
    # 5    +geom_bar(aes(fill=Chr),stat = "identity")是画出柱状图
    # 6    theme_bw()为传统的白色背景和深灰色的网格线
    # 7    theme是参数的设置  plot.title = element_text(hjust = 0.5) 是将title移到中间
                            # panel.grid.major =element_blank(),panel.grid.minor = element_blank()
                            #去除网格线
    
    p2 <- ggplot(dt2,aes(x=Chr,y=C,group=1))+xlab("chrom ID")+ylab("coverage_percent")+labs(title="KPGP-00001")+ylim(0,1.5)+geom_line(aes(color=Chr))+geom_point(aes(color=Chr))+theme_bw()+theme(plot.title = element_text(hjust = 0.5),panel.grid.major =element_blank(),panel.grid.minor = element_blank())
    
    p1
    p2
    dev.off()
    

    最终结果如下


    image.png image.png

    Y染色体的覆盖度特别低,不知道什么原因。

    2.把bam文件按染色体分成小文件,并用IGV查看

    bam文件太大了,有时候把bam文件拆分成小的文件是有必要的

    这里用到一个工具bamtools,它的功能很多,这里选用split的功能

    usage: bamtools [--help] COMMAND [ARGS]
    
    Available bamtools commands:
        convert         Converts between BAM and a number of other formats
        count           Prints number of alignments in BAM file(s)
        coverage        Prints coverage statistics from the input BAM file
        filter          Filters BAM file(s) by user-specified criteria
        header          Prints BAM header information
        index           Generates index for BAM file
        merge           Merge multiple BAM files into single file
        random          Select random alignments from existing BAM file(s), intended more as a testing tool.
        resolve         Resolves paired-end reads (marking the IsProperPair flag as needed)
        revert          Removes duplicate marks and restores original base qualities
        sort            Sorts the BAM file according to some criteria
        split           Splits a BAM file on user-specified property, creating a new BAM output file for each value found
        stats           Prints some basic statistics from input BAM file(s)
    
    See 'bamtools help COMMAND' for more information on a specific command.
    
    
    

    这里只用lane1的bam文件做一个测试

    nohup bamtools split -in KPGP-00001_L1.sorted.bam  -reference &
    #-reference指的是按reference拆分
    

    拆分后,选取文件大小较小的chr19的bam文件,和chrY的文件(正好看看上一部布统计的覆盖度很低是不是统计错误)

    #排序
    samtools sort KPGP-00001_L1.sorted.REF_chrY.bam >chr_Y.sort.bam
    samtools sort KPGP-00001_L1.sorted.REF_chr19.bam >chr_19.sort.bam
    
    
    #建索引
    samtools index chr_Y.sort.bam
    samtools index chr_19.sort.bam
    

    然后把文件导入IGV
    先看一下chrY


    image.png

    可见覆盖度确实很低,并不是之前统计的问题

    再看看chr19

    image.png

    chr19的覆盖程度明显大很多

    3.bam格式转化为bw格式看测序深度分布

    bam文件很大,很多时候才看很不方便。有些时候,我们只需要我们的测序数据在全基因组的测序深度这一个值,并不需要具体某条reads的碱基序列,碱基质量值。这样只需要把bam文件压缩为bw格式。

    同样是只用lane1做测试
    这里用到的一个软件deeptools
    用到它其中的一个工具bamCoverage

    #首先还是要先建立索引
    nohup samtools index KPGP-00001_L1.sorted.bam &
    

    再就是转换格式

    nohup bamCoverage -b KPGP-00001_L1.sorted.bam -o KPGP-00001_L1.sorted.bw &
    

    bw格式的大小才200M,可以轻松的导入IGV,可以从整体看出测序的深度和覆盖度情况。
    比如


    image.png

    很显然,y染色体覆盖度很小

    4.测序深度和GC含量的关系

    首先,把全基因组的bam文件用 mpileup模式输出,根据 1000bp 的窗口滑动来统计每个窗口的测到的碱基数,GC碱基数,测序总深度。因为涉及到测序深度,所以先把各个lane的bam文件merge,再拿merge后的bam文件得到结果的前面一百万行的数据做测试。

    nohup samtools merge KPGP-00001.sorted.merge.bam KPGP-00001_L*.sorted.bam &
    
    samtools mpileup -f /home/ubuntu/WGS_new/input/genome/new/hg38.fa KPGP-00001.sorted.merge.bam KPGP-00001_L*.sorted.bam |head -n 1000000 >1M_mpileup.txt
    

    先看一下输出文件的大概格式(这个文件是之前用lane2的bam做的测试结果)


    image.png

    包括6列:
    分别是:
    染色体号、碱基位置、参考序列对应的碱基、比对上的reads数目(也就是depth)、比对的情况、比对的质量

    命令中之所以加一个-f 参数就是为了提供参考序列fasta,使最终得到的结果文件的第3列是对应的碱基,如果不加,则变成了N,如下

    image.png

    既然加了参考序列,就序列提前对参考序列构建索引,软件要求的是faidx index。

    回到正题
    现在统计测序深度和GC含量的关系,理论上测序得到的reads 拼接的结果应该是和参考序列一致的,因此统计参考序列的GC含量实际上就是统计对应的测序本身的insert 片段的GC含量。然后与此同时统计测序的对应区间的测序深度的值,观察两者的关系。

    python脚本如下

    import sys
    args=sys.argv
    filename=args[1]
    count_depth={}
    count_base={}
    count_number={}
    count_all={}
    with open (filename) as fh:
       for line in fh:
         lineL=line.strip().split("\t")
         chr_ID=lineL[0]
         base_position = int(lineL[1])
         window_position = int(base_position/1000)
         base=lineL[2]
         base.upper() #大写
         depth=int(lineL[3])
         chr_win=chr_ID+"   "+str(window_position)
         if chr_win not in count_base :
              count_base[chr_win]=0
        # if chr_win not in count_depth:      因为两个字典是按同一个key,所以这条可以省略                                                
              count_depth[chr_win]=0
              count_number[chr_win]=0
         if base=="G" or base=="C":
                   count_base[chr_win]+=1
    
         count_depth[chr_win]+=depth
         count_number[chr_win]+=1
         count_all[chr_win]=str(count_base[chr_win])+'      '+str(count_depth[chr_win])+'   '+str(count_number[chr_win]) #把3个字典的value合并成一个字符串作为一个新的字典的value
    for k,v in count_all.items():
       print(k,v,sep="\t")
    
    

    这个脚本写的很长,我相信肯定改进的地方很大,但是这是我自己写的脚本,所以凑活用吧。

    #总结一下:python字典计数的方式可大致分为两种写法
       # 1. if key not in dict:
       #          dict[key]=1 或者其他初始值
       #    else:
       #         dict[key]+=1
    
    
       # 2. if key not in dict:
       #          dict[key]='' 或者 0
       #    dict[key]+=1
    
       #两种用法虽然没什么大的差别,但是有的情况下,2能用的起来,而1不行或更麻烦,比如此脚本情况
       # 其实区别在于1中的if else,执行了if就不会执行else。而2中执行了if会继续执行下面的语句
    
    
    python3 count.py 1M_mpileup.txt |sort -k2,2n >count_all.txt
    
    head count_all.txt
    ---------------
    chr1    9   0   3   1
    chr1    10  0   425756  529
    chr1    11  133 35354   952
    chr1    12  600 46231   1000
    chr1    13  575 41108   1000
    chr1    14  582 51064   1000
    chr1    15  537 30959   1000
    chr1    16  541 28821   1000
    chr1    17  621 51877   1000
    chr1    18  537 34340   1000
    
    -------------------------------------
    

    第一列是染色体号,
    第二列是对应的窗口第几个窗口(从10开始)
    第三列是对应GC碱基数
    第四列是总测序深度
    第五列是每个窗口统计到的碱基总数

    再分别计算一下GC%和mean depth就可以可视化了

    在这之前还是先看看刚统计的结果,可以发现,以1000bp的窗口滑动,统计到的碱基数目并不为1000,有的甚至很低,其实这很容易理解。我的理解是,对于参考基因组,仍然是存在一些含N的重复序列,而这列序列在比对的过程中是不计算的,samtools mpileup 生成的文本中这部分就已经去除了,所以碱基的位置信息不是连续的。而脚本中1000bp是按碱基的位置信息除以1000取int来做的,所以统计到的碱基数目不一致是正常的

    接下来给出可视化的R脚本:

    library(ggplot2)
    dt <- read.table("count.txt") #读入数据
    #head(dt)
    dt$GC <- dt$V3/dt$V5 #得到GC含量
    dt$depth <-dt$V4/dt$V5 #得到平均的depth
    dt <- dt[dt$GC>0,] #把GC等于0的部分去除
    dt <- dt[dt$depth<100,] #把depth大于100的去除
    
    lm_eqn <- function(x,y){
      
      m <- lm(y ~ x);
      
      eq <- substitute(italic(y) == a + b %.% italic(x)*","~~italic(r)^2~"="~r2,
                       
                       list(a = format(coef(m)[1], digits = 2),
                            
                            b = format(coef(m)[2], digits = 2),
                            
                            r2 = format(summary(m)$r.squared, digits = 3)))
      
      as.character(as.expression(eq));
      
    }    #添加线性回归方程
    
    
    
    p <- ggplot(dt, aes(x = GC, y = depth)) +xlim(c(0,0.8))+ylim(c(0,100))+
      geom_smooth(method = "lm", se=FALSE, color="black", formula = y ~ x)+
      geom_point()+geom_text(x=0.6,y=80,label = lm_eqn(dt$GC , dt$depth), parse = TRUE)+theme_bw()+theme(panel.grid = element_blank())
    
    #作图
    

    结果图如下


    image.png

    从这个结果看似乎是负相关,所以再取其他百万行的结果重复一遍,看看是否得到同样的结果

    这是第2000000至3000000之间的图

    image.png

    负相关,不知道什么原因,先不去管它

    Part4 去重复(或标记重复序列)

    以上对比对的横向探索结束
    接下来继续纵向走,下一步是
    去重复(或标记重复序列)
    这里用两种软件:samtools和picard分别处理
    1.samtools
    这里本来应该是用samtools的markdup来标记或去除PCR重复,本来脚本已经写好开始运行了,但是报错了
    脚本如下

    #!/bin/bash
    dir1=~/WGS_new/output/bwa_mapping
    dir2=~/WGS_new/output/bwa_mapping/Dup
    for i in $(seq 1 6)
    do
    samtools markdup -r $dir1/KPGP-00001_L${i}.sorted.bam $dir2/KPGP-00001_L${i}.sorted.rm.bam && echo "rm KPGP-00001_L${i} done"
    samtools markdup -S $dir1/KPGP-00001_L${i}.sorted.bam $dir2/KPGP-00001_L${i}.sorted.mk.bam && echo "mk KPGP-00001_L${i} done"
    done
    
    

    报错信息如下

    [markdup] error: no ms score tag.
    [markdup] error: no ms score tag.
    [markdup] error: no ms score tag.
    [markdup] error: no ms score tag.
    [markdup] error: no ms score tag.
    [markdup] error: no ms score tag.
    [markdup] error: no ms score tag.
    

    仔细看了一下说明书

    Usage:  samtools markdup <input.bam> <output.bam>
    
    Option: 
      -r           Remove duplicate reads
      -l INT       Max read length (default 300 bases)
      -S           Mark supplemenary alignments of duplicates as duplicates (slower).
      -s           Report stats.
      -T PREFIX    Write temporary files to PREFIX.samtools.nnnn.nnnn.tmp.
      -t           Mark primary duplicates with the name of the original in a 'do' tag. Mainly for information and debugging.
          --input-fmt-option OPT[=VAL]
                   Specify a single input file format option in the form
                   of OPTION or OPTION=VALUE
      -O, --output-fmt FORMAT[,OPT[=VAL]]...
                   Specify output format (SAM, BAM, CRAM)
          --output-fmt-option OPT[=VAL]
                   Specify a single output file format option in the form
                   of OPTION or OPTION=VALUE
          --reference FILE
                   Reference sequence FASTA FILE [null]
      -@, --threads INT
                   Number of additional threads to use [0]
    
    The input file must be coordinate sorted and must have gone through fixmates with the mate scoring option on.
    
    

    最后一行说到,必须gone through fixmates with the mate scoring option on
    所以需要先fixmate

    samtools fixmate KPGP-00001_L1.sorted.bam KPGP-00001_L1.sorted.fix.bam
    

    然而又报错了

    [bam_mating_core] ERROR: Coordinate sorted, require grouped/sorted by queryname
    

    bam文件需要按quername排序,而samtools默认是按position排序的,而原始的bam文件为了减少储存,已经被我删除了。。。。
    所以这一步没办法做了,因而samtools markdup去重就不做了,直接用picard的吧

    2.picard
    这里用GATK4的中的picard

    #!/bin/bash
    dir1=~/WGS_new/output/bwa_mapping
    dir2=~/WGS_new/output/bwa_mapping/GATK/Dup
    for i in $(seq 1 6)
    do
    #将重复序列删除,注意--REMOVE_DUPLICATES=true
    gatk MarkDuplicates  --REMOVE_DUPLICATES=true  -I $dir1/KPGP-00001_L${i}.sorted.bam  -M $dir2/KPGP-00001_L${i}.rm_metrics.txt -O $dir2/KPGP-00001_L${i}.rm.bam && echo "rm KPGP-00001_L${i} done"
    
    #只是将重复标记,可以让后续软件识别,但是并没有删除
    gatk MarkDuplicates -I $dir1/KPGP-00001_L${i}.sorted.bam  -M $dir2/KPGP-00001_L${i}.mk_metrics.txt -O $dir2/KPGP-00001_L${i}.mk.bam && echo "mk KPGP-00001_L${i} done"
    done
    
    

    这里先解释为什么要去除重复,这部分节选自解螺旋的矿工公众号

    首先,我们需要先理解什么是重复序列,它是如何产生的,以及为什么需要去除掉?要回答这几个问题,我们需要再次理解在建库和测序时到底发生了什么。

    我们已经知道,在NGS测序之前都需要先构建测序文库:通过物理(超声)打断或者化学试剂(酶切)切断原始的DNA序列,然后选择特定长度范围的序列去进行PCR扩增并上机测序。

    因此,这里重复序列的来源实际上就是由PCR过程中所引入的。因为所谓的PCR扩增就是把原来的一段DNA序列复制多次。可是为什么需要PCR扩增呢?如果没有扩增不就可以省略这一步了吗?

    情况确实如此,但是很多时候我们构建测序文库时能用的细胞量并不会非常充足,而且在打断的步骤中也会引起部分DNA的降解,这两点会使整体或者局部的DNA浓度过低,这时如果直接从这个溶液中取样去测序就很可能漏掉原本基因组上的一些DNA片段,导致测序不全。而PCR扩增的作用就是为了把这些微弱的DNA多复制几倍乃至几十倍,以便增大它们在溶液中分布的密度,使得能够在取样时被获取到。所以这里大家需要记住一个重点,PCR扩增原本的目的是为了增大微弱DNA序列片段的密度,但由于整个反应都在一个试管中进行,因此其他一些密度并不低的DNA片段也会被同步放大,那么这时在取样去上机测序的时候,这些DNA片段就很可能会被重复取到相同的几条去进行测序。看到这里,你或许会觉得,那没必要去除不也应该可以吗?因为即便扩增了多几次,不也同样还是原来的那一段DNA吗?直接用来分析对结果也不会有影响啊!难道不是吗?
    会有影响,而且有时影响会很大!最直接的后果就是同时增大了变异检测结果的假阴和假阳率。主要有几个原因:
    DNA在打断的那一步会发生一些损失,主要表现是会引发一些碱基发生颠换变换(嘌呤-变嘧啶或者嘧啶变嘌呤),带来假的变异。PCR过程会扩大这个信号,导致最后的检测结果中混入了假的结果;
    PCR反应过程中也会带来新的碱基错误。发生在前几轮的PCR扩增发生的错误会在后续的PCR过程中扩大,同样带来假的变异;
    对于真实的变异,PCR反应可能会对包含某一个碱基的DNA模版扩增更加剧烈(这个现象称为PCR Bias)。因此,如果反应体系是对含有reference allele的模板扩增偏向强烈,那么变异碱基的信息会变小,从而会导致假阴。
    PCR对真实的变异检测和个体的基因型判断都有不好的影响。GATK、Samtools、Platpus等这种利用贝叶斯原理的变异检测算法都是认为所用的序列数据都不是重复序列(即将它们和其他序列一视同仁地进行变异的判断,所以带来误导),因此必须要进行标记(去除)或者使用PCR-Free的测序方案(这种方案目前正变得越来越流行,特别是对于RNA-Seq来说尤为重要,现在著名的基因组学研究所——Broad Institute,基本都是使用PCR-Free的测序方案)。


    跑完上面的流程的结果如下:

    image.png

    可以看出只是标记重复的(mk)文件是要比去除重复(rm)文件要大的。

    再看一下之前的bam 文件

    image.png

    很显然这两个处理后的文件都是要比原始文件要大的。

    分别看看mk和rm生成的文件有什么不同

    samtools view KPGP-00001_L1.mk.bam |head
    

    结果如下


    image.png
    samtools view KPGP-00001_L1.rm.bam |head
    
    image.png
    samtools view KPGP-00001_L1.sorted.bam |head
    
    image.png

    很明显,相比原始bam文件,rm多了一些markduplicate的字符,所以文件变大了
    而,相比rm文件,mk,在flag值一列变大了,所以mk比rm文件大,这些通过文件内容很容易看出来

    从下一步开始就直接用mk文件

    因为如果 MarkDuplicates 这步把重复去掉,则会对 mate 信息产生影响,可以考虑在这步之后加上 FixMateInformation。
    但是如果只是 MarkDuplicates而没有去除重复,则不会对mate信息产生影响,理论上不需要 FixMateInformation这一步

    这个可以在哪得到论证呢

    我们可以看看上面对3个bam文件查看的内容,对比flag值
    (荧光标出来的部分)

    mk.bam rm.bam sort.bam
    1187 99 163
    99 163 99
    1123 163 99
    163 99 163
    1123 99 99

    image.png
    image.png
    image.png

    结果显而易见

    Part5 碱基质量重校正

    先下载一些必备数据库

    #!/bin/bash
    wget ftp://gsapubftp-anonymous@ftp.broadinstitute.org/bundle/hg38/1000G_phase1.snps.high_confidence.hg38.vcf.gz
    wget ftp://gsapubftp-anonymous@ftp.broadinstitute.org/bundle/hg38/1000G_phase1.snps.high_confidence.hg38.vcf.gz.tbi
    wget ftp://gsapubftp-anonymous@ftp.broadinstitute.org/bundle/hg38/Mills_and_1000G_gold_standard.indels.hg38.vcf.gz
    wget ftp://gsapubftp-anonymous@ftp.broadinstitute.org/bundle/hg38/Mills_and_1000G_gold_standard.indels.hg38.vcf.gz.tbi
    wget ftp://gsapubftp-anonymous@ftp.broadinstitute.org/bundle/hg38/hapmap_3.3.hg38.vcf.gz
    wget ftp://gsapubftp-anonymous@ftp.broadinstitute.org/bundle/hg38/hapmap_3.3.hg38.vcf.gz.tbi
    wget ftp://gsapubftp-anonymous@ftp.broadinstitute.org/bundle/hg38/dbsnp_146.hg38.vcf.gz
    wget ftp://gsapubftp-anonymous@ftp.broadinstitute.org/bundle/hg38/dbsnp_146.hg38.vcf.gz.tbi
    
    

    结果如下

    total 5.1G
    -rw-rw-r-- 1 ubuntu ubuntu 1.8G Aug 11 00:52 1000G_phase1.snps.high_confidence.hg38.vcf.gz
    -rw-rw-r-- 1 ubuntu ubuntu 2.1M Aug 11 01:07 1000G_phase1.snps.high_confidence.hg38.vcf.gz.tbi
    -rw-rw-r-- 1 ubuntu ubuntu 3.2G Aug 11 03:04 dbsnp_146.hg38.vcf.gz
    -rw-rw-r-- 1 ubuntu ubuntu 2.4M Aug 11 03:20 dbsnp_146.hg38.vcf.gz.tbi
    -rw-rw-r-- 1 ubuntu ubuntu  837 Aug 10 23:17 download.sh
    -rw-rw-r-- 1 ubuntu ubuntu  60M Aug 11 01:08 hapmap_3.3.hg38.vcf.gz
    -rw-rw-r-- 1 ubuntu ubuntu 1.5M Aug 11 01:08 hapmap_3.3.hg38.vcf.gz.tbi
    -rw-rw-r-- 1 ubuntu ubuntu  20M Aug 11 01:07 Mills_and_1000G_gold_standard.indels.hg38.vcf.gz
    -rw-rw-r-- 1 ubuntu ubuntu 1.5M Aug 11 01:07 Mills_and_1000G_gold_standard.indels.hg38.vcf.gz.tbi
    
    

    在此之前先把之前下载的hg38.fa构建dict,注意dict和之前的bwa构建的index不一样

    cd /home/ubuntu/WGS_new/input/genome/new
    nohup gatk CreateSequenceDictionary -R hg38.fa -O hg38.dict &
    

    创建了字典之后就可以继续了

    #!/bin/bash
    snp=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/resource/dbsnp_146.hg38.vcf.gz
    indel=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/resource/Mills_and_1000G_gold_standard.indels.hg38.vcf.gz
    #dir1=~/WGS_new/output/bwa_mapping
    dir2=~/WGS_new/output/bwa_mapping/GATK/Dup
    #dir3=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/index
    dir4=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/resource
    dir5=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/recal
    
    ref=~/WGS_new/input/genome/new/hg38.fa
    for i in $(seq 1 6)
    do
    gatk BaseRecalibrator -R $ref -I $dir2/KPGP-00001_L${i}.mk.bam --known-sites $snp --known-sites $indel -O $dir5/KPGP-00001_L${i}.mk_recal.table
    done
    
    

    得到的table文件只是一个中间文件,还需要一步才能得到BQSR后的bam文件。

    #!/bin/bash
    snp=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/resource/dbsnp_146.hg38.vcf.gz
    indel=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/resource/Mills_and_1000G_gold_standard.indels.hg38.vcf.gz
    #dir1=~/WGS_new/output/bwa_mapping
    dir2=~/WGS_new/output/bwa_mapping/GATK/Dup
    #dir3=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/index
    dir4=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/resource
    dir5=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/recal
    
    ref=~/WGS_new/input/genome/new/hg38.fa
    #for i in $(seq 1 6)
    #do
    #gatk BaseRecalibrator -R $ref -I $dir2/KPGP-00001_L${i}.mk.bam --known-sites $snp --known-sites $indel -O $dir5/KPGP-00001_L${i}.mk_recal.table
    #done
    
    
    
    for i in $(seq 1 6)
    do
    gatk  ApplyBQSR -R $ref -I $dir2/KPGP-00001_L${i}.mk.bam -bqsr $dir5/KPGP-00001_L${i}.mk_recal.table -O $dir5/KPGP-00001_L${i}.mk_bqsr.bam
    done
    
    

    好了,到了这一步,利用生成的高质量的bam,接下来就是用4种工具来找变异,分别是GATK、bcftools、freebayes、varscan
    再这之前先将各个lane生成的bam文件合并

    nohup samtools merge KPGP-00001_bqsr.merge.bam *.bam 
    

    Part6 找变异

    1.GATK
    先对上一步生成的merge的bam文件建立索引

     nohup samtools index KPGP-00001_bqsr.merge.bam &
    

    然后是使用GATK的HaplotypeCaller

    
    

    2.bcftools

    #!/bin/bash
    snp=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/resource/dbsnp_146.hg38.vcf.gz
    indel=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/resource/Mills_and_1000G_gold_standard.indels.hg38.vcf.gz
    #dir1=~/WGS_new/output/bwa_mapping
    dir2=~/WGS_new/output/bwa_mapping/GATK/Dup
    #dir3=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/index
    dir4=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/resource
    dir5=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/recal
    dir6=/home/ubuntu/WGS_new/output/bwa_mapping/GATK/vcf
    
    ref=~/WGS_new/input/genome/new/hg38.fa
    
    samtools mpileup -ugf $ref $dir5/KPGP-00001_bqsr.merge.bam | bcftools call --thread 6 -v -m -O z  -o $dir6/KPGP-00001_bqsr.vcf.gz
    
    

    相关文章

      网友评论

      本文标题:WGS学习全流程笔记

      本文链接:https://www.haomeiwen.com/subject/ogtuvftx.html