# General Paint By Py

> 编写 Python + matplotlib 绘图脚本，生成教材级（教科书排版风格）的数学/物理教学插图与数据图——包括网格/表格式图形、数学结构示意图、物理场景图、函数曲线图，并渲染输出 PNG 或 SVG。当用户提出"画/绘制/生成/做一张图、figure、chart、示意图、diagram、illustration"等请求、给出一段需要转为图片的详细视觉规格、或要求修改一个现有绘图脚本时使用。

- Skill: `locusyuri/general-paint-by-py` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add locusyuri/general-paint-by-py`
- Raw SKILL.md: https://api.skillmd.com/api/skills/locusyuri/general-paint-by-py/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: locusyuri (https://skillmd.com/u/locusyuri)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/locusyuri/general-paint-by-py

---


# General Paint By Py

## Overview

本 skill 把一次性的"画一张图"请求，转化为规范、可复现、符合所在仓库输出约定的 matplotlib 绘图脚本，而不是凭记忆即兴写一段无法对齐规格的代码。核心做法：**先把用户描述的画面翻译成确定性的数据与规则（并对规则做断言校验），再按既定脚本骨架实现、运行、交付**。

生成目标可以是透明 PNG（默认）或不透明白色背景 SVG/PNG（当规格或仓库约定要求时）。在 `physics-viz` 仓库的 `src/math_paper/` 下，必须使用 SVG 预设（见 `references/project-conventions.md`）。

## 何时使用

- 用户请求新建图形：从一句描述到包含精确规格的长 prompt 都属于此范围。
- 用户请求修改现有绘图脚本：先完整读取该脚本与其同目录脚本，理解既有结构与约定后再改。
- 规格模糊时不要停下来反复追问：用合理默认值补齐并在回复中注明假设，一次交付、允许按反馈迭代。

## 工作流

### Step 1 — 解析规格，翻译成数据与规则

把画面描述逐条转成程序里的**确定性数据**，避免在绘制中途"临场发明"：

- 布局类：行/列数、网格单元次序、面板数量与并排方式、坐标范围。
- 内容类：哪些对象出现、按什么规则上色/删除线/加粗（分类集合、公式、最小素因子等）。
- 用显式列表/集合/字典常量表达分类，例如"哪些是素数、每类有几个"。
- 凡是有可验证计数的地方（如"共 74 个合数、49 个偶数"），在脚本末尾写 `assert`，运行即可证明规则被完整实现。
- 把最终规则的要点写进模块 docstring（这也成为后续维护与用户核对时的单一来源）。

### Step 2 — 规划版面与层级

在写代码前确定：

- 单面板 or 多面板；多面板时各子图要视觉等宽/等物理尺度。
- 用数据坐标 + `set_aspect("equal")` 的结构示意（网格、矩形、几何图），还是普通绘图轴（曲线、极坐标）。
- 是否需要坐标轴刻度/边框（示意类图通常 `axis("off")`，曲线图保留浅色刻度）。
- 元素层级 zorder 习惯：填充 0 → 网格/底图 1 → 主线条 2~3 → 箭头 4 → 点与文字 5+。
- 图例/角注/说明文字的位置与字号；图内文字语言遵循仓库约定（本项目英文）。

### Step 3 — 编写绘图脚本

- 按该仓库最接近的既有脚本复制骨架（`build_figure()` / `main()` / `if __name__ == "__main__"`），只替换面板逻辑，见 `references/matplotlib-patterns.md` 的模板。
- 输出配置一律使用共享 `Presets`，需要微调时用 `dataclasses.replace`，不要手写裸 `figsize`/`dpi`（见 `references/project-conventions.md`）。
- 段落式注释（`# -- xxx ----`）划分逻辑区块；关键常量放在文件顶部集中定义（颜色、尺寸、字体大小）。
- 公式/变量一律用 matplotlib mathtext（`r"$E = kq/r^2$"`），不要拼 unicode 数学符号混入正文。

### Step 4 — 运行并交付

- 从仓库根执行：`uv run python src/.../xxx.py`。
- 脚本无错误地生成文件即视为完成——**不要调用任何视觉/看图工具去复查生成的图片**，用户会自己查看；只需确认保存路径并报告。
- 除非用户明确要求，不要创建绘图脚本与输出文件之外的额外文件。

### Step 5 — 自查（写代码时完成，而非运行后）

- `assert` 校验所有可计数规则。
- 文字/标注是否可能画出坐标边界（扩展 `xlim/ylim` 或用 offset points 标注）。
- 是否遵守输出背景约定（规格要白色背景必须显式 `transparent=False`）。
- 运行 lints 并清理新引入错误。

## 教科书风格图形准则（检查表）

- **干净第一**：无阴影、无渐变、无装饰性花边，除非规格明确要求；浅灰细网格线（`#dddddd`~`#d5d5d5`）代替深色边框。
- **配色**：学术风格常量色即可，保持全图一致。常用：墨色文字 `#333/#1a1a1a`、深蓝 `#1f4e9b`、亮蓝 `#2196F3/#2980b9`、红 `#c0392b/#E53935`、橙 `#e67e22`、绿 `#27ae60/#2e8b57`、浅灰 `#999/#888`。填充区用同色系淡粉彩（alpha 0.2~0.35 或浅色十六进制）。
- **文字层级**：主标签 ≥ 标注 ≈ 图例 > 刻度（如 13 / 10~12 / 8~9 pt）；一致字号，不做花哨字重（粗体只用于强调，如幸存素数）。
- **线宽**：主曲线 1.8~2.2，辅助/参考线 0.6~0.9，边框 0.8~1.6。
- **zorder 分层**：先画的在底层；显式写 zorder 防止被覆盖（如"删除线压在数字上"）。
- **坐标细节**：结构图 `axis("off")` + `set_aspect("equal")`；曲线图去 top/right spine、浅刻度；等比面板用同一物理尺度的坐标范围。
- **图例**：手动构造 `Line2D` handles + `legend(..., frameon=True, facecolor="white", edgecolor="#cccccc")`，比让 matplotlib 推断更可控。
- **不要大标题**除非规格要求；图内唯一说明文字一般放图例/角注。

## 资源

- `references/matplotlib-patterns.md` — 可复用的代码片段库：脚本骨架、多面板、补丁、箭头、删除线/网格、图例、mathtext、刻度、常见坑。**写任何绘图代码前先读它**。
- `references/project-conventions.md` — 本仓库输出约定：目录结构、Preset 选择（math_paper 强制 SVG、其余默认透明 PNG）、背景设置、运行命令。**在 physics-viz 里绘图必须先读它**。

