群体结构分析的绘图脚本,基于sns

成图效果
usage:
python draw_step4.structure.py -n UPGMA.nwk --fam ./SNP_maf0.05_miss0.5.fam -Q ./SNP_maf_miss_ld -K 6 -o test.pdf

脚本

首先导入需要用到的包。--order和-n都是用于指定顺序的,有一个参数就可以了。其他都是必选参数。

import argparse

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from matplotlib.patches import Patch

from Bio import Phylo

sns.set_style("darkgrid")

# 创建ArgumentParser对象
parser = argparse.ArgumentParser(description="draw a population structure plot")

# 添加外部参数
parser.add_argument('-n', "--newick", type=str, help='input a newick file')
parser.add_argument('--order', type=str, help='input an ordered sample name list')
parser.add_argument("-f", "--fam", type=str, help="input the order of bed")
parser.add_argument('-Q', type=str, help="the structure.Q path")
parser.add_argument('-K', type=int, help="the number of Q")
parser.add_argument('-o', "--output", type=str, help='output the population structure plot pdf')

args = parser.parse_args()

核心的排序函数和绘图函数

def read_nwk(nwk: str,root:str=None) -> list:
    tree = Phylo.read(nwk, "newick")
    if root:
        new_root_clade = tree.common_ancestor(root)
        tree.root_with_outgroup(new_root_clade)
    nwk_list = [clade.name for clade in tree.get_terminals()][::-1]
    return nwk_list


def read_structure_Q(prefix_path: str, order_list: list, i: int, fam_list: list) -> pd.DataFrame:
    df = pd.read_csv(f"{prefix_path}.{str(i)}.Q", sep=" ", header=None)
    df.index = fam_list
    df = df.T[order_list]
    return df


def draw_structure(df: pd.DataFrame, n: int, cmap: sns.cubehelix_palette, axes) -> None:
    for i in range(len(df)):
        sns.barplot(x=df.columns, y=df.iloc[i], color=cmap[i], bottom=np.sum(df.iloc[:i], axis=0), ax=axes[n],
                    dodge=False,
                    width=1, edgecolor='w')

读入数据,调颜色

# 读入数据
fam = args.fam
K = args.K
prefix_path = args.Q
nwk = args.newick

fam_list = [x.split(" ")[0] for x in open(fam, "rt").readlines()]
if args.order:
    print(args.order)
    order = args.order
    order_list = [x.split("\t")[0] for x in open(order, "rt").readlines()]
else:
    order_list = read_nwk(nwk)
cmap = sns.color_palette("hls", n_colors=K)

画图

中间上色的部分和自己的order.list有关,颜色也是自己去调(某个的颜色对应某个亚群)

# 给所有文字放大到两倍
sns.set(context='notebook', style='ticks', font_scale=2)
fig, axes = plt.subplots(nrows=K - 1, ncols=1, figsize=(70, K * 2))

for i in range(2, K + 1):
    # 读 Q 矩阵并调顺序
    df = read_structure_Q(prefix_path, order_list, i, fam_list)
    n = i - 2

    if n == K - 2:
        # cmap[3], cmap[1], cmap[0], cmap[2] = cmap[0], cmap[3], cmap[2], cmap[1]
        # 每次循环画一张图出来
        draw_structure(df, n, cmap, axes)
        # 最后一行保留样本名
        axes[n].set(xlabel="", ylabel=f"K={i}", yticks=[])
        # 旋转 x 轴标签
        axes[n].set_xticklabels(axes[n].get_xticklabels(), rotation=45, ha='right')
        # 上色
        # for i, label in enumerate(axes[n].xaxis.get_ticklabels()):
        #     if 1 < i < 30:
        #         color = cmap[3]
        #     elif 29 < i < 51:
        #         color = cmap[1]
        #     elif 50 < i < 66:
        #         color = cmap[0]
        #     elif 65 < i < 77:
        #         color = cmap[2]
        #     elif 76 < i < 90:
        #         color = cmap[4]
        #     else:
        #         color = "black"
        #     label.set_color(color)

        # 处理标签和颜色
        # legend_labels = {'Tropical': cmap[3], 'Lancaster': cmap[1], 'P_group': cmap[0], 'Reid': cmap[2], 'IDT': cmap[4],
        #                  "Mixed": "black"}  # 用于存储图例标签
        # legend_patches = []  # 用于存储图例的 Patch 对象
        # for label, color in legend_labels.items():
        #     legend_patches.append(Patch(color=color, label=label))
        # axes[K - 2].legend(handles=legend_patches, loc='upper center', bbox_to_anchor=(0.5, -0.8), ncol=K + 1)

    else:
        draw_structure(df, n, cmap, axes)
        axes[n].set(xlabel="", xticks=[], ylabel=f"K={i}", yticks=[])

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