统计nucmer的比对结果

脚本由GPT生成
运行完nucmer后,想要知道每条染色体的比对情况

nucmer --mum -t 6 -b 500 ref.fa query.fa -p ref.query
delta-filter -1 -l 500 ref.query.delta > ref.query.filtered.delta
show-coords -H -c -l -o -r -T ref.query.filtered.delta > ref.query.filtered.coords
#ref.query.filtered.coords 就是输入文件

cat merge.gap.analyze_alignment.py

#统计nucmer的比对结果
#nucmer --mum -t 6 -b 500 ref.fa query.fa -p ref.query
#delta-filter -1 -l 500 ref.query.delta > ref.query.filtered.delta
#show-coords -H -c -l -o -r -T ref.query.filtered.delta > ref.query.filtered.coords
#ref.query.filtered.coords 就是本脚本的输入文件

#Usage: python merge.gap.analyze_alignment.py $i.filtered.coords -rag=200000 > $i.200kgap.stat.txt
#-rag=的含义是如果相邻的比对片段在两个基因组上的距离都小于 rag,则合并
#比如-rag=30000的时候
#704513  705497   72524266  72525272  --> 初始比对片段
#721485  723852   72549371  72551732  --> 15988 和 25105 都 < 30000,所以合并
#
#合并后
#704513  723852   72524266  72551732

#Ref_Chr    ref基因组 染色体
#Qry_Chr    query基因组 染色体
#Total_Aligned_Length   合并后的总比对长度
#Ref_Coverage(%)    ref基因组 染色体被 query基因组 覆盖的比例
#Qry_Coverage(%)    query基因组 染色体被 ref基因组 覆盖的比例
#
import sys
from collections import defaultdict

def parse_coords(file_path, rag_threshold):
    """ 解析coords文件,并根据rag阈值合并片段 """
    chr_stats = defaultdict(lambda: defaultdict(list))  # 按 (ref_chr, qry_chr) 存储片段
    with open(file_path, "r") as f:
        for line in f:
            cols = line.strip().split("\t")
            if len(cols) < 13:
                continue  # 确保数据完整

            # 提取必要信息
            ref_chr, qry_chr = cols[11], cols[12]  # 染色体名称
            ref_start, ref_end = int(cols[0]), int(cols[1])  # 参考基因组位置
            qry_start, qry_end = int(cols[2]), int(cols[3])  # 查询基因组位置
            ref_length, qry_length = int(cols[7]), int(cols[8])  # 染色体总长

            chr_stats[ref_chr][qry_chr].append((ref_start, ref_end, qry_start, qry_end, ref_length, qry_length))

    # 合并片段
    merged_stats = defaultdict(lambda: defaultdict(list))
    for ref_chr, qry_dict in chr_stats.items():
        for qry_chr, segments in qry_dict.items():
            segments.sort()  # 按 ref_start 排序
            merged = []
            current_start, current_end, qry_start, qry_end, ref_len, qry_len = segments[0]

            for i in range(1, len(segments)):
                ref_s, ref_e, qry_s, qry_e, _, _ = segments[i]
                ref_gap = ref_s - current_end
                qry_gap = qry_s - qry_end

                if ref_gap <= rag_threshold and qry_gap <= rag_threshold:
                    # 合并
                    current_end = max(current_end, ref_e)
                    qry_end = max(qry_end, qry_e)
                else:
                    merged.append((current_start, current_end, qry_start, qry_end, ref_len, qry_len))
                    current_start, current_end, qry_start, qry_end = ref_s, ref_e, qry_s, qry_e

            # 添加最后一个片段
            merged.append((current_start, current_end, qry_start, qry_end, ref_len, qry_len))
            merged_stats[ref_chr][qry_chr] = merged

    return merged_stats

def compute_coverage(merged_stats):
    """ 计算合并后的覆盖度和比对长度 """
    results = []
    for ref_chr, qry_dict in merged_stats.items():
        for qry_chr, segments in qry_dict.items():
            total_aligned_length = sum(seg[1] - seg[0] + 1 for seg in segments)
            ref_length = segments[0][4] if segments else 1  # 参考染色体长度
            qry_length = segments[0][5] if segments else 1  # 查询染色体长度
            coverage_ref = (total_aligned_length / ref_length) * 100 if ref_length > 0 else 0
            coverage_qry = (total_aligned_length / qry_length) * 100 if qry_length > 0 else 0
            results.append((ref_chr, qry_chr, total_aligned_length, coverage_ref, coverage_qry))

    return results

def main():
    # 检查命令行参数
    if len(sys.argv) != 3:
        print("Usage: python merge_and_analyze.py <filtered.coords> -rag <threshold>")
        sys.exit(1)

    coords_file = sys.argv[1]
    rag_threshold = int(sys.argv[2].replace("-rag=", ""))

    # 解析并合并
    merged_stats = parse_coords(coords_file, rag_threshold)
    results = compute_coverage(merged_stats)

    # 输出结果(支持 `>` 重定向)
    print("Ref_Chr\tQry_Chr\tTotal_Aligned_Length\tRef_Coverage(%)\tQry_Coverage(%)")
    for ref_chr, qry_chr, aligned_length, coverage_ref, coverage_qry in results:
        print(f"{ref_chr}\t{qry_chr}\t{aligned_length}\t{coverage_ref:.2f}\t{coverage_qry:.2f}")

if __name__ == "__main__":
    main()

cat analyze_alignment.py

#统计nucmer的比对结果
#nucmer --mum -t 6 -b 500 ref.fa query.fa -p ref.query
#delta-filter -1 -l 500 ref.query.delta > ref.query.filtered.delta
#show-coords -H -c -l -o -r -T ref.query.filtered.delta > ref.query.filtered.coords
#ref.query.filtered.coords 就是本脚本的输入文件
#Usage: python analyze_alignment.py $i.filtered.coords > $i.200kgap.stat.txt

#输出解释
#Ref_Chr    ref基因组染色体名称
#Qry_Chr    query基因组染色体名称
#Aligned_Regions    比对区段数量
#Total_Aligned_Length   参考染色体和目标染色体的比对总长度(bp)
#Ref_Coverage(%)    ref基因组 该染色体比对到 query基因组 的比例 (aligned_length / ref_length * 100)
#Qry_Coverage(%)    query基因组 该染色体被 ref基因组 覆盖的比例 (aligned_length / qry_length * 100)
#Average_Identity   平均序列相似度


import sys
from collections import defaultdict

# 检查是否传入了文件路径
if len(sys.argv) != 2:
    print("Usage: python analyze_alignment.py <filtered.coords>")
    sys.exit(1)

coords_file = sys.argv[1]  # 从命令行参数获取输入文件

# 统计数据结构
chr_stats = defaultdict(lambda: defaultdict(lambda: {"count": 0, "aligned_length": 0, "total_identity": 0, "ref_length": 0, "qry_length": 0}))

# 读取 filtered.coords 文件并解析数据
with open(coords_file, "r") as f:
    for line in f:
        cols = line.strip().split("\t")
        if len(cols) < 13:
            continue  # 确保数据完整
        
        ref_chr = cols[11]  # Chicken.T2T 染色体
        qry_chr = cols[12]  # Falco_naumanni 染色体
        length = int(cols[5])  # 比对长度
        identity = float(cols[6])  # 相似度
        ref_length = int(cols[7])  # Chicken.T2T 染色体总长度
        qry_length = int(cols[8])  # Falco_naumanni 染色体总长度
        
        # 更新参考基因组(Chicken.T2T)比对情况
        chr_stats[ref_chr][qry_chr]["count"] += 1
        chr_stats[ref_chr][qry_chr]["aligned_length"] += length
        chr_stats[ref_chr][qry_chr]["total_identity"] += identity * length  # 加权相似度
        chr_stats[ref_chr][qry_chr]["ref_length"] = ref_length  # 参考染色体长度
        chr_stats[ref_chr][qry_chr]["qry_length"] = qry_length  # 目标染色体长度

# 打印结果(支持重定向到文件)
print("Ref_Chr\tQry_Chr\tAligned_Regions\tTotal_Aligned_Length\tRef_Coverage(%)\tQry_Coverage(%)\tAverage_Identity")
for ref_chr, qry_dict in chr_stats.items():
    for qry_chr, stats in qry_dict.items():
        avg_identity = stats["total_identity"] / stats["aligned_length"] if stats["aligned_length"] > 0 else 0
        coverage_ref = (stats["aligned_length"] / stats["ref_length"]) * 100 if stats["ref_length"] > 0 else 0
        coverage_qry = (stats["aligned_length"] / stats["qry_length"]) * 100 if stats["qry_length"] > 0 else 0
        print(f"{ref_chr}\t{qry_chr}\t{stats['count']}\t{stats['aligned_length']}\t{coverage_ref:.2f}\t{coverage_qry:.2f}\t{avg_identity:.2f}")


©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容