# -*- coding: utf-8 -*-
"""
教程示例图生成脚本 Part A —— 示意图类
图 01 技术路线图 | 图 02 中心法则与转录组 | 图 03 细胞死亡方式
图 04 焦亡分子机制 | 图 05 公共数据库全景 | 图 15 论文结构

说明：这些是教学示意图（matplotlib 手绘），用于教程讲解；
读者在真实分析中应使用自己的数据与 R 脚本生成发表级图。
运行：python gen_figures_partA_schematics.py   （输出到 ../../figures/）
"""
import os
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch, Circle, Rectangle, Ellipse
import matplotlib.patches as mpatches

plt.rcParams["font.sans-serif"] = ["Microsoft YaHei", "SimHei"]
plt.rcParams["axes.unicode_minus"] = False

OUT = os.path.join(os.path.dirname(__file__), "..", "..", "figures")
os.makedirs(OUT, exist_ok=True)

# 配色
C_BLUE   = "#4C72B0"
C_ORANGE = "#DD8452"
C_GREEN  = "#55A868"
C_RED    = "#C44E52"
C_PURPLE = "#8172B3"
C_GREY   = "#8C8C8C"


def fig01_technical_route():
    """图01 技术路线图：竖向流程图"""
    fig, ax = plt.subplots(figsize=(7.2, 10.4))
    ax.set_xlim(0, 10); ax.set_ylim(0, 15); ax.axis("off")

    steps = [
        ("① 选题与假设", "焦亡相关基因在肝细胞癌(HCC)中的\n表达特征与预后价值", C_BLUE),
        ("② 数据获取", "TCGA-LIHC（371 癌 + 50 癌旁）\nGSE14520（GEO 独立验证队列）", C_BLUE),
        ("③ 数据预处理", "注释转换 · 去批次 · 归一化 · 质控", C_GREEN),
        ("④ 差异表达分析", "limma：|log2FC|>1 & adj.P<0.05\n火山图 · 热图 · PCA", C_GREEN),
        ("⑤ 功能富集分析", "GO / KEGG / GSEA\n(clusterProfiler)", C_ORANGE),
        ("⑥ PPI 网络与 hub 基因", "STRING + Cytoscape/cytoHubba\nMCC 打分筛选核心基因", C_ORANGE),
        ("⑦ 生存分析与预后模型", "KM 曲线 · 单/多因素 Cox\nLASSO 构建风险评分", C_RED),
        ("⑧ 独立验证", "GEO 队列验证 · HPA 蛋白水平验证\nROC 评估预测效能", C_RED),
        ("⑨ 论文撰写与投稿", "结果解读 → IMRaD 结构成稿 →\n期刊投稿（生信挖掘类）", C_PURPLE),
    ]
    n = len(steps)
    y = 14.6
    dy = 1.62
    for i, (title, desc, color) in enumerate(steps):
        box = FancyBboxPatch((0.7, y - 0.62), 8.6, 1.24,
                             boxstyle="round,pad=0.06,rounding_size=0.18",
                             linewidth=1.6, edgecolor=color, facecolor="white")
        ax.add_patch(box)
        ax.text(1.0, y + 0.18, title, fontsize=11.5, fontweight="bold", color=color, va="center")
        ax.text(1.0, y - 0.28, desc, fontsize=8.6, color="#333333", va="center")
        if i < n - 1:
            ax.annotate("", xy=(5.0, y - 0.75), xytext=(5.0, y - 0.75 - dy + 1.24),
                        arrowprops=dict(arrowstyle="-|>", color="#999999", lw=1.6))
        y -= dy
    ax.set_title("细胞焦亡相关基因肝细胞癌生信挖掘课题 · 技术路线图",
                 fontsize=14, fontweight="bold", pad=8)
    fig.tight_layout()
    fig.savefig(os.path.join(OUT, "fig01_technical_route.png"), dpi=150)
    plt.close(fig)


def fig02_central_dogma():
    """图02 中心法则 + 转录组测序概念"""
    fig, axes = plt.subplots(1, 2, figsize=(11.5, 4.6), gridspec_kw={"width_ratios": [1, 1.25]})
    ax = axes[0]
    ax.set_xlim(0, 10); ax.set_ylim(0, 6); ax.axis("off")

    def gene_box(x, y, w, h, label, color, fs=11):
        box = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.05,rounding_size=0.15",
                             linewidth=1.8, edgecolor=color, facecolor="white")
        ax.add_patch(box)
        ax.text(x + w / 2, y + h / 2, label, ha="center", va="center", fontsize=fs, color=color)

    gene_box(3.2, 4.1, 3.6, 1.1, "DNA（基因）", C_BLUE)
    gene_box(3.2, 2.2, 3.6, 1.1, "mRNA", C_GREEN)
    gene_box(3.2, 0.3, 3.6, 1.1, "蛋白质", C_ORANGE)
    ax.annotate("转录 transcription", xy=(6.9, 4.65), xytext=(8.0, 5.0),
                arrowprops=dict(arrowstyle="-|>", color=C_GREEN, lw=2), fontsize=9.5, color=C_GREEN)
    ax.annotate("翻译 translation", xy=(6.9, 2.75), xytext=(8.0, 3.0),
                arrowprops=dict(arrowstyle="-|>", color=C_ORANGE, lw=2), fontsize=9.5, color=C_ORANGE)
    ax.text(5.0, 0.02, "中心法则（简化）", ha="center", fontsize=10, color="#666666")
    ax.set_title("(a) 中心法则", fontsize=12, fontweight="bold")

    ax2 = axes[1]
    ax2.set_xlim(0, 10); ax2.set_ylim(0, 6); ax2.axis("off")
    steps2 = [
        ("组织样本", "肿瘤 / 癌旁", C_BLUE, 8.1, 4.6, 1.7, 0.85),
        ("提取总 RNA", "富集 mRNA", C_BLUE, 8.1, 3.6, 1.7, 0.85),
        ("逆转录 → cDNA", "文库构建", C_GREEN, 8.1, 2.6, 1.7, 0.85),
        ("高通量测序", "RNA-seq", C_ORANGE, 8.1, 1.6, 1.7, 0.85),
        ("定量表达矩阵", "基因 × 样本", C_RED, 8.1, 0.6, 1.7, 0.85),
    ]
    for label, sub, color, x, y, w, h in steps2:
        box = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.05,rounding_size=0.15",
                             linewidth=1.6, edgecolor=color, facecolor="#FAFAFA")
        ax2.add_patch(box)
        ax2.text(x + w / 2, y + h * 0.68, label, ha="center", va="center", fontsize=10, color=color, fontweight="bold")
        ax2.text(x + w / 2, y + h * 0.28, sub, ha="center", va="center", fontsize=8, color="#555555")
    for i in range(4):
        y0 = 4.6 - i * 1.0
        ax2.annotate("", xy=(8.95, y0 - 0.82), xytext=(8.95, y0),
                     arrowprops=dict(arrowstyle="-|>", color="#999999", lw=1.5))
    ax2.text(1.2, 3.3, "mRNA 表达量\n≈ 基因活性", fontsize=10.5, color="#555555", va="center",
             bbox=dict(boxstyle="round", facecolor="#FFF3E0", edgecolor=C_ORANGE, alpha=0.8))
    ax2.set_title("(b) 转录组测序得到表达量", fontsize=12, fontweight="bold")
    fig.tight_layout()
    fig.savefig(os.path.join(OUT, "fig02_central_dogma.png"), dpi=150)
    plt.close(fig)


def fig03_cell_death():
    """图03 细胞死亡方式对比（2×3 面板示意）"""
    fig, axes = plt.subplots(2, 3, figsize=(12.5, 7.2))
    panels = [
        ("凋亡 apoptosis", "细胞皱缩、膜出泡\n半胱天冬酶介导\n免疫沉默", C_BLUE),
        ("焦亡 pyroptosis", "膜穿孔、细胞肿胀\nGSDMD/GSDME 成孔\n促炎（IL-1β/IL-18）", C_RED),
        ("坏死 necrosis", "膜破裂、内容物外泄\n被动发生\n强烈炎症", C_GREY),
        ("铁死亡 ferroptosis", "铁依赖脂质过氧化\nGPX4 抑制\n形态：线粒体嵴减少", C_ORANGE),
        ("自噬性死亡 autophagy", "自噬体大量形成\n溶酶体降解\n可促存活或促死亡", C_GREEN),
        ("坏死性凋亡 necroptosis", "RIPK1/RIPK3/MLKL\n程序性坏死\n促炎", C_PURPLE),
    ]
    for ax, (title, desc, color) in zip(axes.flat, panels):
        ax.set_xlim(0, 10); ax.set_ylim(0, 10); ax.axis("off")
        # 画一个示意细胞
        if "焦亡" in title:
            cell = Ellipse((5, 5), 6.4, 5.4, facecolor="#FDECEA", edgecolor=color, lw=2.2)
            ax.add_patch(cell)
            for px, py in [(3.4, 5.8), (5.2, 4.4), (6.6, 6.2), (4.4, 3.6), (6.2, 3.2)]:
                ax.add_patch(Circle((px, py), 0.34, facecolor="white", edgecolor=color, lw=1.3, hatch="//"))
        elif "铁死亡" in title:
            cell = Circle((5, 5), 2.9, facecolor="#FFF7E6", edgecolor=color, lw=2.2)
            ax.add_patch(cell)
            ax.plot([4.2, 5.0, 5.8], [4.6, 6.6, 4.4], color=color, lw=1.6, ls="--")
            ax.text(5, 3.0, "Fe2+  ·  ROS", ha="center", fontsize=8.5, color=color)
        elif "自噬" in title:
            cell = Circle((5, 5), 2.9, facecolor="#EAF6EC", edgecolor=color, lw=2.2)
            ax.add_patch(cell)
            ax.add_patch(Circle((5, 5.6), 1.0, facecolor="white", edgecolor=color, lw=1.4))
            ax.add_patch(Circle((4.6, 5.2), 0.35, facecolor=color))
            ax.add_patch(Circle((5.4, 6.0), 0.25, facecolor=color))
        elif "坏死性凋亡" in title:
            cell = Circle((5, 5), 2.9, facecolor="#F0EAF8", edgecolor=color, lw=2.2)
            ax.add_patch(cell)
            ax.plot([3.2, 6.8], [3.8, 6.2], color=color, lw=1.5)
            ax.plot([3.4, 6.6], [6.2, 3.8], color=color, lw=1.5)
        elif "凋亡" in title:
            cell = Ellipse((5, 5), 4.6, 3.6, facecolor="#EAF2FB", edgecolor=color, lw=2.2)
            ax.add_patch(cell)
            for px, py in [(4.0, 5.6), (5.4, 4.4), (6.0, 6.0)]:
                ax.add_patch(Circle((px, py), 0.42, facecolor="white", edgecolor=color, lw=1.2))
        else:  # 坏死
            cell = Circle((5, 5), 2.9, facecolor="#F2F2F2", edgecolor=color, lw=2.2)
            ax.add_patch(cell)
            ax.add_patch(mpatches.Polygon([(3.6, 4.2), (4.0, 5.4), (3.4, 6.2), (4.4, 5.6), (5.0, 6.6)],
                                          closed=True, color="#BBBBBB", alpha=0.8))
        ax.set_title(title, fontsize=12, fontweight="bold", color=color)
        ax.text(5, 1.15, desc, ha="center", va="center", fontsize=8.6, color="#444444")
    fig.suptitle("细胞死亡方式对比（焦亡是炎症性程序性细胞死亡）", fontsize=14, fontweight="bold", y=1.0)
    fig.tight_layout(rect=[0, 0, 1, 0.96])
    fig.savefig(os.path.join(OUT, "fig03_cell_death.png"), dpi=150)
    plt.close(fig)


def fig04_pyroptosis_mechanism():
    """图04 焦亡分子机制（经典/非经典通路）"""
    fig, ax = plt.subplots(figsize=(10.8, 7.2))
    ax.set_xlim(0, 14); ax.set_ylim(0, 10); ax.axis("off")

    def box(x, y, w, h, label, color, fs=9.5, fc="white"):
        b = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.05,rounding_size=0.12",
                           linewidth=1.5, edgecolor=color, facecolor=fc)
        ax.add_patch(b)
        ax.text(x + w / 2, y + h / 2, label, ha="center", va="center", fontsize=fs, color="#222222")

    # 左：经典通路
    box(0.8, 8.2, 4.4, 1.0, "PAMPs / DAMPs\n（细菌毒素、损伤信号）", C_BLUE)
    box(0.8, 6.4, 4.4, 1.0, "NLRP3 炎症小体\n(NLRP3+ASC+pro-caspase-1)", C_BLUE)
    box(0.8, 4.6, 4.4, 1.0, "caspase-1（活化）", C_RED)
    box(0.8, 1.4, 4.4, 2.4, "GSDMD 裂解 → N-GSDMD\n在膜上打孔\n细胞肿胀破裂 → 焦亡", C_RED)
    box(4.8, 6.2, 3.6, 1.6, "pro-IL-1β / pro-IL-18\n→ IL-1β / IL-18 释放", C_ORANGE)
    for y0, y1 in [(7.8, 7.5), (6.0, 5.7)]:
        ax.annotate("", xy=(3.0, y1), xytext=(3.0, y0), arrowprops=dict(arrowstyle="-|>", color="#555555", lw=1.6))
    ax.annotate("", xy=(3.0, 4.2), xytext=(3.0, 3.9), arrowprops=dict(arrowstyle="-|>", color="#555555", lw=1.6))
    ax.annotate("", xy=(6.6, 7.6), xytext=(5.2, 7.6), arrowprops=dict(arrowstyle="-|>", color=C_ORANGE, lw=1.6))
    ax.annotate("", xy=(6.4, 5.8), xytext=(6.4, 6.1), arrowprops=dict(arrowstyle="-|>", color=C_ORANGE, lw=1.4))
    ax.text(3.0, 9.35, "经典焦亡通路", fontsize=12, fontweight="bold", color=C_BLUE, ha="center")

    # 右：非经典通路
    box(9.4, 8.2, 3.8, 1.0, "胞内 LPS\n（革兰阴性菌）", C_PURPLE)
    box(9.4, 6.4, 3.8, 1.0, "caspase-4/5/11", C_PURPLE)
    box(9.4, 4.6, 3.8, 1.0, "GSDMD 裂解 → 成孔", C_RED)
    box(9.4, 2.6, 3.8, 1.2, "NLRP3 炎症小体旁路激活\nIL-1β 释放", C_ORANGE)
    for y0, y1 in [(7.8, 7.5), (6.0, 5.7)]:
        ax.annotate("", xy=(11.3, y1), xytext=(11.3, y0), arrowprops=dict(arrowstyle="-|>", color="#555555", lw=1.6))
    ax.annotate("", xy=(11.3, 4.2), xytext=(11.3, 3.9), arrowprops=dict(arrowstyle="-|>", color="#555555", lw=1.6))
    ax.annotate("", xy=(11.3, 2.5), xytext=(11.3, 2.6 - 0.05), arrowprops=dict(arrowstyle="-|>", color=C_ORANGE, lw=1.4))
    ax.text(11.3, 9.35, "非经典焦亡通路", fontsize=12, fontweight="bold", color=C_PURPLE, ha="center")

    # 底部：GSDME / 化疗药
    box(5.6, 0.5, 7.4, 1.1, "GSDME 通路：化疗药物 → caspase-3 → GSDME 裂解 → 焦亡（与凋亡共存）",
        C_GREEN, fs=9)
    ax.text(7.0, 9.7, "细胞焦亡（pyroptosis）分子机制", fontsize=14, fontweight="bold", ha="center")
    fig.tight_layout()
    fig.savefig(os.path.join(OUT, "fig04_pyroptosis_mechanism.png"), dpi=150)
    plt.close(fig)


def fig05_databases():
    """图05 公共数据库全景图"""
    import networkx as nx
    G = nx.Graph()
    G.add_node("公共数据库", size=4600, color=C_RED)
    nodes = [
        ("TCGA", "肿瘤组学+临床", C_BLUE, 2500),
        ("GEO", "表达谱数据仓库", C_BLUE, 2500),
        ("GTEx", "正常组织表达", C_GREEN, 2200),
        ("HPA", "蛋白表达定位", C_GREEN, 2200),
        ("STRING", "蛋白互作 PPI", C_ORANGE, 2400),
        ("KEGG", "通路数据库", C_ORANGE, 2200),
        ("GO", "基因本体注释", C_ORANGE, 2200),
        ("cBioPortal", "癌症组学可视化", C_PURPLE, 2200),
        ("TIMER/GEPIA", "免疫浸润/在线分析", C_PURPLE, 2200),
    ]
    pos = {n: (0, 0) for n, *_ in nodes}
    import math
    for i, (name, desc, color, size) in enumerate(nodes):
        G.add_node(name, size=size, color=color)
        G.add_edge("公共数据库", name)
        ang = i / len(nodes) * 2 * math.pi - math.pi / 2
        pos[name] = (3.6 * math.cos(ang), 3.0 * math.sin(ang))
    pos["公共数据库"] = (0, 0)
    sizes = [G.nodes[n]["size"] for n in G.nodes]
    colors = [G.nodes[n]["color"] for n in G.nodes]
    fig, ax = plt.subplots(figsize=(10.5, 8.2))
    nx.draw_networkx_edges(G, pos, ax=ax, edge_color="#CCCCCC", width=1.4)
    nx.draw_networkx_nodes(G, pos, ax=ax, node_size=sizes, node_color=colors, alpha=0.92,
                           edgecolors="white", linewidths=2)
    labels = {n: n for n in G.nodes}
    nx.draw_networkx_labels(G, pos, labels, font_size=10.5, font_weight="bold",
                            font_color="white", ax=ax)
    for name, desc, color, size in nodes:
        x, y = pos[name]
        ax.text(x, y - 0.62, desc, ha="center", fontsize=8.6, color="#444444")
    ax.set_xlim(-5.2, 5.2); ax.set_ylim(-4.2, 4.4); ax.axis("off")
    ax.set_title("本课题使用的公共数据库", fontsize=14, fontweight="bold")
    fig.tight_layout()
    fig.savefig(os.path.join(OUT, "fig05_databases.png"), dpi=150)
    plt.close(fig)


def fig15_paper_structure():
    """图15 论文结构（IMRaD）与图表对照"""
    fig, ax = plt.subplots(figsize=(11.5, 5.6))
    ax.set_xlim(0, 16); ax.set_ylim(0, 7); ax.axis("off")
    secs = [
        ("Title\n题目", "提炼核心发现", C_BLUE, 0.5),
        ("Abstract\n摘要", "背景/方法/结果/结论", C_BLUE, 3.0),
        ("Introduction\n引言", "背景+缺口+假设", C_GREEN, 5.5),
        ("Methods\n方法", "数据来源+分析流程", C_GREEN, 8.0),
        ("Results\n结果", "图表+统计+发现", C_ORANGE, 10.5),
        ("Discussion\n讨论", "解读+局限+展望", C_RED, 13.0),
    ]
    for title, desc, color, x in secs:
        b = FancyBboxPatch((x, 3.4), 2.2, 2.4, boxstyle="round,pad=0.06,rounding_size=0.14",
                           linewidth=1.6, edgecolor=color, facecolor="white")
        ax.add_patch(b)
        ax.text(x + 1.1, 5.3, title.split("\n")[0], ha="center", fontsize=10.5, fontweight="bold", color=color)
        ax.text(x + 1.1, 4.7, title.split("\n")[1] if "\n" in title else "", ha="center", fontsize=8.5, color="#555555")
        ax.text(x + 1.1, 3.95, desc, ha="center", fontsize=8, color="#555555")
    # 底部：图表对照
    ax.text(8.0, 2.4, "结果章节的图表安排", ha="center", fontsize=11, fontweight="bold", color="#333333")
    figs = [
        ("Fig.1", "技术路线", 0.8), ("Fig.2", "表达/差异（火山图、热图）", 3.4),
        ("Fig.3", "功能富集（GO/KEGG）", 6.6), ("Fig.4", "PPI 与 hub 基因", 9.6),
        ("Fig.5", "生存分析（KM/森林图）", 12.4),
    ]
    for label, desc, x in figs:
        b = FancyBboxPatch((x, 0.5), 2.9, 1.3, boxstyle="round,pad=0.05,rounding_size=0.1",
                           linewidth=1.3, edgecolor=C_PURPLE, facecolor="#F6F1FB")
        ax.add_patch(b)
        ax.text(x + 1.45, 1.45, label, ha="center", fontsize=9.5, fontweight="bold", color=C_PURPLE)
        ax.text(x + 1.45, 0.95, desc, ha="center", fontsize=7.8, color="#444444")
    ax.text(8.0, 6.55, "生信挖掘论文的 IMRaD 结构与图表安排", fontsize=13.5, fontweight="bold", ha="center")
    fig.tight_layout()
    fig.savefig(os.path.join(OUT, "fig15_paper_structure.png"), dpi=150)
    plt.close(fig)


if __name__ == "__main__":
    fig01_technical_route()
    fig02_central_dogma()
    fig03_cell_death()
    fig04_pyroptosis_mechanism()
    fig05_databases()
    fig15_paper_structure()
    print("Part A done:", sorted(os.listdir(OUT)))
