0. Core constraints (non-negotiable)
| Constraint | Specification |
|---|---|
| Font size | Body font size small four (12pt) = \normalsize (TikZ) = font.size=13 (matplotlib);Prohibited \small、\footnotesize |
| Whitespace | Not too large; standalone border 10–15pt;matplotlib bbox_inches="tight" |
| Occlusion | No content may be occluded (except axis legend); text must be strictly separated from arcs/nodes |
| Color scheme | Restrained top-journal style; schematic diagrams ≤ 5 hues, data plots ≤ 3–4 hues;ProhibitedLight gray (#999999、#CCCCCC etc.), rainbow prohibited |
| Compiler | TikZ must use xelatex(pdflatex prohibited) |
| Output | matplotlib always outputs SVG; TikZ outputs PDF → export SVG |
1. Decision tree: choosing the technical route
需要画什么?
│
├─ 示意图 / 原理图 / 机制图 / 架构图 / 流程图 / 网络拓扑图 / 扇形图 / 同心圆
│ └─→ TikZ(xelatex 编译)
│
├─ 数据图:曲线、折线、散点、热图、雷达、柱状、ROC
│ └─→ Python matplotlib
│
└─ 算法伪代码
└─→ LaTeX article + algorithm2e
2. TikZ quick workflow
# 1. 新建 figures/子目录/fig.tex(从下方模板开始)
# 2. 开调试网格确认位置
# 3. 编译
cd figures/子目录/ && xelatex -interaction=nonstopmode fig.tex
# 4. 预览
pdftoppm -r 200 -png fig.pdf fig_preview && mv fig_preview-1.png fig.png
# 5. 确认无遮挡后导出 SVG
pdftocairo -svg fig.pdf fig.svg
# 6. 清理
rm -f *.aux *.log *.fls *.fdb_latexmk fig_preview*.png
Preamble that must be included:
\documentclass[border={15pt 10pt 10pt 10pt}]{standalone}
% border 顺序:left bottom right top(非 CSS 顺序!)
\usepackage{xeCJK}
\setCJKmainfont{PingFang SC}
\usepackage{tikz}
\usetikzlibrary{positioning, shapes.geometric, arrows.meta, fit, calc, backgrounds}
\usepackage{xcolor}
3. matplotlib quick workflow
# 1. 新建 figures/子目录/fig.py(从下方模板开始)
# 2. 运行
python3 figures/子目录/fig.py
# 3. 验证 SVG 输出
ls figures/子目录/fig.svg
File header must include (copy into every script):
import matplotlib.pyplot as plt
import matplotlib.font_manager as _fm
import os, sys
_SANS_PATH = "/Users/sunyue/Library/Fonts/SourceHanSansCN-Regular.ttf"
_fm.fontManager.addfont(_SANS_PATH) # 必须在 rcParams 之前
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['Source Han Sans CN', 'PingFang SC', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.size'] = 13 # 小四 ≈ 13pt(正文对齐)
plt.rcParams['axes.titlesize'] = 20
plt.rcParams['axes.labelsize'] = 16
plt.rcParams['xtick.labelsize'] = 13
plt.rcParams['ytick.labelsize'] = 13
plt.rcParams['legend.fontsize'] = 13
plt.rcParams['figure.dpi'] = 150
_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(_SCRIPT_DIR, "..")) # 调整层级
from color_palette import BLUE, RED, BLACK, GRID_COLOR, GRID_ALPHA, SPINE_COLOR, SPINE_WIDTH
Standard axes style (required for every figure):
ax.spines[["top", "right"]].set_visible(False)
for sp in ["left", "bottom"]:
ax.spines[sp].set_color(SPINE_COLOR)
ax.spines[sp].set_linewidth(SPINE_WIDTH)
ax.tick_params(axis="both", width=2.0, length=6, colors=BLACK, pad=5)
ax.grid(True, ls=":", lw=2.0, color=GRID_COLOR, alpha=GRID_ALPHA)
Save (must be SVG + bbox_inches="tight"):
plt.tight_layout()
plt.savefig(os.path.join(_SCRIPT_DIR, "fig.svg"), format="svg", bbox_inches="tight")
legend (do not pass both prop and fontsize):
ax.legend(loc="upper right", frameon=True, framealpha=0.85,
edgecolor=BLACK, prop={'size': 13}) # ← 只用 prop,不加 fontsize=
4. Color quick reference
Recommended: IEEE/Springer dark blue + dark gray
\definecolor{colPrimary}{RGB}{31,73,125} % IEEE 深蓝
\definecolor{colSecondary}{RGB}{64,64,64} % 深灰
\definecolor{colArrow}{RGB}{30,30,30} % 近黑箭头
Nature low saturation (pie charts/pie charts)
\definecolor{clrGreen}{HTML}{8FBCB2} % 灰绿
\definecolor{clrBlue} {HTML}{8AAAC8} % 灰蓝
\definecolor{clrPurple}{HTML}{A99DC4} % 灰紫
\definecolor{clrWarm} {HTML}{C8AD8A} % 灰暖
Python primary palette (figures/color_palette.py imported uniformly)
BLUE="#1D4ED8" RED="#DC2626" GREEN="#16A34A" AMBER="#F59E0B" PURPLE="#7C3AED"
Prohibited colors:#999999、#CCCCCC、#EEEEEE and other light grays; pure primary colors #FF0000、#00FF00; mixing 4 or more colors.
6. Multi-Agent plotting-review iterative workflow (must be followed)
Core principle: Every figure must pass an independent review agent using
look_atto read the PNG and confirm item by item before it is considered complete. The main Agent is prohibited from self-review—must not claim a figure is complete without calling the review agent.
6.1 Agent division of labor
| Agent role | Responsibility | Allowed tools | Prohibited tools |
|---|---|---|---|
| Plotting Agent | Writes .tex/.py, compiles/runs, generates PNG previews; may use look_at to self-check obvious errors and fix them independently |
Write, Edit, Bash, look_at | — |
| Review Agent | Calls look_at to read the PNG, checks the inspection checklist item by item, returns PASS / FAIL + parameter-level revision suggestions |
look_at | Write, Edit, Bash |
| Main Agent (you) | Distributes tasks, receives results, coordinates iteration; exports SVG after receiving PASS | task(), background_output() | — |
6.2 Complete execution flow (must follow this order)
Step 1 ── 主 Agent 启动绘图 Agent(run_in_background=false)
task(category="unspecified-high", run_in_background=false,
description="绘制 [图名]", prompt="[见 §6.4 绘图 Agent 首次模板]")
→ 获得 session_id_draw(保存!)
→ 获得 fig.png 路径
Step 2 ── 主 Agent 启动审查 Agent(run_in_background=false)
task(category="unspecified-low", run_in_background=false,
description="审查 [图名]", prompt="[见 §6.4 审查 Agent 模板,含 fig.png 绝对路径]")
→ 获得 session_id_review(保存!)
→ 获得 PASS 或 FAIL+问题列表
Step 3 ── 若 PASS → 主 Agent 执行导出 SVG(pdftocairo -svg),任务完成
若 FAIL → 继续 Step 4
Step 4 ── 主 Agent 续接绘图 Agent(session_id=session_id_draw)
task(session_id=session_id_draw, run_in_background=false,
prompt="审查结果 FAIL,问题如下:\n[粘贴 FAIL 列表]\n请修改并重新生成 fig.png。")
→ 获得新 fig.png
Step 5 ── 主 Agent 续接审查 Agent(session_id=session_id_review)
task(session_id=session_id_review, run_in_background=false,
prompt="图已更新,请重新 look_at([fig.png绝对路径]) 并逐条核查。")
→ 获得新一轮 PASS 或 FAIL
Step 6 ── 重复 Step 4–5,最多 3 轮。
超过 3 轮仍 FAIL → 主 Agent 直接介入阅读 FAIL 列表,判断是否需要架构重设计(非渐进修改)
Strict rules:
- Each review round must use a new
look_atcall (must not judge from memory or the previous round's conclusion)- The Plotting Agent must regenerate the PNG after every modification (must not reuse old images)
- The main Agent must not skip the review step and directly claim that "the figure is complete"
6.3 Review Agent checklist (check item by item after each look_at, output □✓ / □✗)
【字体】
□ 所有文字是否清晰可读(与正文字号相当)?
□ 是否存在疑似 \small / \footnotesize 的过小字号?
□ 中文是否正常显示(无方块乱码)?
【遮挡】(最高优先级,任意一项 ✗ 即 FAIL)
□ 是否有文字压在圆弧/线条/节点边框上?
□ 是否有节点互相重叠(非刻意)?
□ 是否有箭头穿过文字或节点内容?
□ legend/图例是否遮挡关键数据区域?
【布局与留白】
□ 图形边距是否合适(standalone border 10–15pt,不过大也不被裁剪)?
□ 各列/各行间距是否均匀,无明显疏密不均?
□ 是否有内容超出图形边框被裁剪?
【配色】
□ 是否使用了浅灰(视觉接近 #999999 / #CCCCCC 的低对比色)?
□ 色相数量是否在限制内(示意图 ≤5,数据图 ≤4)?
□ 标注文字颜色是否与对应线条/元素保持一致?
【整体】
□ 图的信息是否清晰传达(结构/流程/层次一目了然)?
□ 图形整体是否对称/平衡(无明显偏斜)?
Review Agent return format (strictly followed):
PASS — 所有 □✓,无问题。
或
FAIL
□✓ 字体:文字清晰可读
□✓ 字体:中文正常
□✗ 遮挡:标注"发射波束"文字压在虚线箭头线上 → 建议 yshift=-20pt(当前 -8pt 不足)
□✗ 字体:右下角"输出"节点文字偏小,疑似 \small → 改为 \normalsize
□✓ 布局:边距合适
□✗ 留白:右侧空白过多(目测约 3cm)→ border right 从 20pt 缩至 10pt
□✓ 配色:无浅灰,色相数量合规
□✓ 整体:信息传达清晰
6.4 Main Agent dispatch prompt templates
Drawing Agent (first time):
TASK: 根据以下要求创建 [图名] 的 TikZ/matplotlib 代码,编译并生成预览 PNG。
EXPECTED OUTCOME:
- 文件已创建:[绝对路径/fig.tex] 或 [绝对路径/fig.py]
- 编译/运行成功(无 Error、无 Warning 级字体缺失)
- PNG 已生成:[绝对路径/fig.png](-r 200 分辨率)
REQUIRED TOOLS: Write, Edit, Bash
MUST DO:
- 从 scientific-drawing/SKILL.md §2(TikZ)或 §3(matplotlib)模板出发
- TikZ 用 xelatex 编译;matplotlib 用 python3 运行
- TikZ 生成 PNG 命令:
pdftoppm -r 200 -png fig.pdf fig_preview && mv fig_preview-1.png fig.png
- 严格遵守 references/elements.md 和 references/tikz-rules.md 所有规则
- 每次小改后立即重新编译确认,不批量改动后才编译
MUST NOT DO:
- 不导出 SVG(审查通过后由主 Agent 执行)
- 不使用 \small、\footnotesize、pdflatex
- 可用 look_at 自查明显问题并自行修正,但最终质检由审查 Agent 独立完成
CONTEXT:
- 图的需求:[具体描述]
- 技能路径:[skill-root-path]/
- 输出目录:[figures/子目录/]
Review Agent (each round):
TASK: 视觉审查 [绝对路径/fig.png],逐条核查标准检验清单,返回 PASS 或 FAIL+问题列表。
EXPECTED OUTCOME:
- 对 §6.3 每条检查项输出 □✓ 或 □✗
- 若存在 □✗,每条给出:问题描述 + 定位到 TikZ/matplotlib 参数级别的修改建议
REQUIRED TOOLS: look_at(仅此一项)
MUST DO:
- 第一步必须调用 look_at,参数 file_path=[绝对路径/fig.png],goal="检查字体大小、文字遮挡、节点重叠、边距留白、配色"
- 按 §6.3 检验清单顺序逐条输出结果
- 对每个 □✗ 给出具体参数修改建议(如:yshift=-20pt、border right=10pt、改 \normalsize)
MUST NOT DO:
- 不修改任何代码文件
- 不执行任何编译或运行命令
- 不根据代码推断图的外观——必须基于 look_at 实际图像内容判断
CONTEXT:
- 图片路径:[绝对路径/fig.png]
- 原始需求:[...]
- 检验清单:见 scientific-drawing/SKILL.md §6.3
Drawing Agent (iterative modification, must continue session_id):
task(
session_id="[上一轮绘图 Agent 的 session_id]",
run_in_background=False,
prompt="""审查 Agent 返回 FAIL,问题如下:
[粘贴完整 FAIL 列表,含每条 □✗ 和参数级修改建议]
请按上述问题逐条修改 fig.tex/fig.py,重新编译,重新生成 fig.png。
修改完成后,输出:已修改项目列表 + 新 fig.png 的绝对路径。"""
)
Review Agent (continue review, must continue session_id):
task(
session_id="[上一轮审查 Agent 的 session_id]",
run_in_background=False,
prompt="""绘图 Agent 已完成修改,新图已生成。
请重新调用 look_at([绝对路径/fig.png]) 并按 §6.3 检验清单重新逐条核查,返回新一轮 PASS 或 FAIL+问题列表。
注意:必须基于新图实际内容判断,不得复用上轮结论。"""
)
- TikZ layout and templates:references/tikz-rules.md
- When to read: multi-column layout / y-coordinate management / debug grid / layout-level Bug quick reference table
- Drawing rules for each element:references/elements.md
- When to read: node shapes / arrows (fan-in, fan-out, cross annotations) / layer labels / fit boxes / background layers / fan charts / concentric circles / divider lines / element-level Bug quick reference table
- matplotlib full rules:references/matplotlib-rules.md
- When to read: font registration / legend / spines / output / pitfall fixes
- Color scheme specification:references/color-standards.md
- When to read: color selection principles / color selection by chart type / TikZ color palette / annotation text coloring / Python desaturation tool
- Color scheme JSON reference library:references/color-palettes.json
- When to read: need specific hex values / choose a theme palette (
themes.*) / qualitative, sequential, diverging palette arrays
- When to read: need specific hex values / choose a theme palette (
- Compilation and export:references/compile-export.md
- When to read: compilation commands / PDF→SVG / cleanup / macOS cairo issues