Python--从VCF文件中提取出各个样本的变异信息,并按特定的格式重新组织这些数据

        VCF文件包含了基因组中的变异信息以及与样本相关的数据。对于BSA(Bulked Segregant Analysis)重测序分析,我们希望更直观地查看各个样本在特定位点的变异信息,包括变异深度和变异频率。为了实现这一目标,本次编写了一个Python脚本,用于提取和重新组织VCF文件中的数据。

这个脚本的主要功能包括:

        1)从VCF文件中解析数据,包括染色体位置、参考碱基、可变碱基等。

        2)提取每个样本的基因型信息,包括杂合、纯合等。

        3)获取每个样本的变异深度和变异频率。

        4)动态构建基因型映射,以确定每个样本的变异类型。

        5)将处理后的数据按特定格式重新组织。

        6)将处理后的数据写入输出文件,以便进一步分析和可视化。

        下面是我的vcf文件内容,因为在vcf文件里看起来不太方便,这里我把vcf文件里的内容复制到excel中看一下。

图片

下面是经过脚本处理后输出的文件

图片

这样我们就可以以这种方式去看各个样本相对于参考基因组的变异以及样本之间的变异了。

一、在windows下rstudio中的运行脚本

input_file = 'D:/data_deal/test/test58/test.all.clean.snp.vcf'
output_file = 'D:/data_deal/test/test58/out-test.all.clean.snp.txt'

# 初始化一个空字典来映射基因型
genotype_mapping = {}

# 初始化一个列表来保存样本名称
sample_names = []

# 初始化一个列表来保存处理后的数据行
output_data = []

with open(input_file, 'r') as infile:
    for line in infile:
        if line.startswith('#CHROM'):
            parts = line.strip().split('\t')
            sample_names = parts[9:]  # 获取样本名称

            # 构建标题行
            header = ['#CHROM', 'POS', 'REF', 'ALT']
            for sample_name in sample_names:
                header.extend([sample_name, 'Depth', 'AlleDp'])
            output_data.append(header)

        if not line.startswith('#'):
            # 分割行,获取所需的列
            parts = line.strip().split('\t')
            chrom = parts[0]
            pos = parts[1]
            ref = parts[3]
            alt = parts[4]

            # 获取样本数据列
            sample_data = parts[9:]

            # 初始化列表来保存处理后的数据
            new_sample_data = []

            for data in sample_data:
                # 分割样本数据列
                sample_parts = data.split(':')

                # 提取基因型信息
                genotype = sample_parts[0]

                # 获取Depth和AlleDp
                ad = sample_parts[1].split(',')
                depth = sample_parts[2]
                alle_dp = ','.join(ad)

                # 动态构建基因型映射
                genotype_mapping[genotype] = f'{ref},{alt}'

                # 处理0/0(0|0)和1/1(1|1)的情况,只写入和REF或ALT列一致的值
                if genotype in ('0/0', '0|0'):
                    base_type = ref
                elif genotype in ('1/1', '1|1'):
                    base_type = alt
                else:
                    base_type = genotype_mapping.get(genotype, '')

                # 构建处理后的样本数据列
                new_sample_info = [base_type, depth, alle_dp]
                new_sample_data.extend(new_sample_info)

            # 构建数据行
            data_row = [chrom, pos, ref, alt] + new_sample_data
            output_data.append(data_row)

# 打开输出文件并将处理后的数据写入
with open(output_file, 'w') as outfile:
    for data_row in output_data:
        outfile.write('\t'.join(data_row) + '\n')

​​

二、在linux中运行

下面是在linux下具体运行vcf_processor.py步骤

图片

下面是vcf_processor.py脚本的全部内容


import sys

if len(sys.argv) != 3:
    print(f"Usage: python {sys.argv[0]} <input_file_vcf> <output_file>")
    sys.exit(1)

input_file = sys.argv[1]
output_file = sys.argv[2]

# 初始化一个空字典来映射基因型
genotype_mapping = {}

# 初始化一个列表来保存样本名称
sample_names = []

# 初始化一个列表来保存处理后的数据行
output_data = []

with open(input_file, 'r') as infile:
    for line in infile:
        if line.startswith('#CHROM'):
            parts = line.strip().split('\t')
            sample_names = parts[9:]  # 获取样本名称

            # 构建标题行
            header = ['#CHROM', 'POS', 'REF', 'ALT']
            for sample_name in sample_names:
                header.extend([sample_name, 'Depth', 'AlleDp'])
            output_data.append(header)

        if not line.startswith('#'):
            # 分割行,获取所需的列
            parts = line.strip().split('\t')
            chrom = parts[0]
            pos = parts[1]
            ref = parts[3]
            alt = parts[4]

            # 获取样本数据列
            sample_data = parts[9:]

            # 初始化列表来保存处理后的数据
            new_sample_data = []

            for data in sample_data:
                # 分割样本数据列
                sample_parts = data.split(':')

                # 提取基因型信息
                genotype = sample_parts[0]

                # 获取Depth和AlleDp
                ad = sample_parts[1].split(',')
                depth = sample_parts[2]
                alle_dp = ','.join(ad)

                # 动态构建基因型映射
                genotype_mapping[genotype] = f'{ref},{alt}'

                # 处理0/0(0|0)和1/1(1|1)的情况,只写入和REF或ALT列一致的值
                if genotype in ('0/0', '0|0'):
                    base_type = ref
                elif genotype in ('1/1', '1|1'):
                    base_type = alt
                else:
                    base_type = genotype_mapping.get(genotype, '')

                # 构建处理后的样本数据列
                new_sample_info = [base_type, depth, alle_dp]
                new_sample_data.extend(new_sample_info)

            # 构建数据行
            data_row = [chrom, pos, ref, alt] + new_sample_data
            output_data.append(data_row)

# 打开输出文件并将处理后的数据写入
with open(output_file, 'w') as outfile:
    for data_row in output_data:
        outfile.write('\t'.join(data_row) + '\n')

        整个脚本的思路是从输入的VCF文件的第10列开始处理数据。它首先解析VCF文件中的各列,然后针对每个样本的数据,提取和处理基因型信息、深度信息等,最后将处理后的数据重新组织并写入到输出文件中。

        注:本次脚本没有考虑ALT有两个的情况。因为我在前面过滤vcf文件时,使用参数min_alleles 2,max_alleles 2,只保留了vcf文件ALT列只有一种碱基的情况。

        补充:FORMAT 为后面10列信息的说明列,通常以":"隔开各个缩写词。不同的变异检测软件可能会有差异,以下用GATK的检测结果为例:

        第10列(包含)以后为样品基因型列,各信息以":"分隔与FORMAT列一一对应;

        GT 表示genotype,通常用/ or |分隔两个数字,|phase过也就是杂合的两个等位基因知道哪个等位基因来自哪条染色体;0代表参考基因组的碱基类型;1代表ALT碱基类型的第一个碱基(多个碱基用","分隔),2代表ALT第二个碱基。,以此类推;比如 REF列为:A, ALT列为G,T;那么0/1基因型为AG 杂合,1/1基因型为GG纯合SNP;1/2代表GT基因型;./.表示缺失;

        AD 两种碱基各自支持的碱基数量,用","分开两个数据,分别代表两个等位基因的深度;

        DP 该样品该变异位点的测序深度总和,也就是AD两个数字的和;

        PL 归一化后各基因型的可能性,通常有三个数字用','隔开,顺序对应AA,AB,BB基因型,A代表REF,B代表ALT(也就是0/0, 0/1, and 1/1),由于是归一化之后,数值越小代表基因型越可靠;那么最小的数字对应的基因型判读为该样品的最可能的基因型;(provieds the likelihoods of the given genotypes)

        GQ针对PL的判读得到的基因型的质量值,此值越大基因型质量值越好。由于PL归一化之后通常最小的数字为0;那么基因型的质量值取PL中第二小的数字,如果第二小的数字大于99,我们只取99,因为在GATK中再大的值是没有意义的,第二小的数大于99的话一般说明基因型的判读是很可靠的,只有当第二小的数小于99的时候,才有必要怀疑基因型的可靠性。

        补充内容来自:https://www.omicsclass.com/article/6

        之前的脚本忘了考虑vcf里面对0/0和1/1格式的另一种书写形式0|0和1|1了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: bcftools是一个广泛使用的命令行工具,用于处理VCF格式变异调用数据。它支持检查,过滤,转换和合并VCF文件。利用bcftools可以生成高保真度和高质量的系统发育树。 构建系统发育树必须先生成一个vcf文件。在vcf文件,包含了每个样品在每个位置上的碱基。然后,可以使用bcftools进行变异的过滤和筛选,以过滤掉低质量的碱基以及不太可靠的变异。 在变异筛选之后,可以使用bcftools将过滤后的vcf文件转换为phylip格式。phylip是一种用于构建系统发育树的标准格式。然后,利用phylip格式文件和其他的支持文件,可以使用常规的系统发育树软件,如RAxML和PhyML,构建系统发育树。 总之,bcftools是一个非常有用的工具,能够对VCF格式变异调用数据进行全面处理,并可以生成高质量的系统发育树。它对于分子生物学和生物信息学研究都是非常重要的工具。 ### 回答2: BCFTools是一个非常流行的工具,可以用于处理VCF文件并构建系统发育树。使用BCFTools处理VCF文件有很多好处,例如可以过滤VCF文件无用的信息,筛选感兴趣的位点等。 要使用BCFTools构建系统发育树,我们需要先将VCF文件数据转换成BCF文件。这可以通过使用bcftools view命令将VCF文件转换成BCF文件来完成。然后,我们需要使用bcftools query命令从BCF文件提取需要的信息,例如基因型、SNP位点等。可以使用bcftools filter命令在提取信息的同时进行一些筛选操作,例如过滤掉低质量的位点、过滤掉缺失值等。 最后,在得到所需的信息后,我们可以使用构建系统发育树所需的软件,例如PHYLIP等,将提取信息输入到软件进行分析和构建系统发育树。 总之,使用BCFTools处理VCF文件可以大大简化系统发育树的构建过程,提高分析效率和准确性。但是,需要注意保证数据质量和正确性,以避免结果错。 ### 回答3: BCFtools是一种用于处理VCF和BCF文件的工具集,可以用于构建系统发育树。通过将多个样品的VCF文件合并以构建总体样本VCF文件,可以使用BCFtools执行操作,例如基因型过滤、缺失数据的填充以及变异注释。 构建系统发育树需要将样品的遗传差异映射到树形结构,以显示它们的亲缘关系。一种构建方法是使用多序列比对将DNA序列对齐,然后执行基于序列比较的树形建构分析。另一种方法是使用变异的相对频率或一些组合遗传标志,例如单倍体基因型的分布来建构系统发育树。这种数据分析方法称为分子系统学。 使用BCFtools进行VCF文件处理时,可以考虑以下步骤: 1)使用bcftools merge命令将多个样本VCF文件合并成一个总体VCF文件。 2)使用bcftools view命令执行过滤,例如基因型和质量过滤,以减少噪音和杂质信号。 3)使用bcftools stats命令生成统计信息,例如变异密度、每个样本的基因型频率和分布的质量值等。 4)使用vcftools或其他变异注释工具添加有关变异和功能信息,例如GenBank注释、GO注释、KEGG通路注释等。 5)使用获得的信息变异进行系统发育推断,以判断样本之间的亲缘关系、进化史和分化历史。常见的分化历史分析方法包括最大简约树、相似度矩阵分析、邻接成对绘制等分子系统学方法。 综上所述,BCFtools是一种有用的工具集,可以处理VCF文件和构建系统发育树,并帮助科学家了解样本之间的遗传相似性和进化历史。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值