统计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}")


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容