{"id":"plotting-agent","name":"plotting-agent","summary":"PaperOrchestraパイプラインのステップ2(arXiv:2604.05018)。outline.jsonから可視化計画を実行してください。","body":"# Plotting Agent (Step 2)\n\nFaithful implementation of the Plotting Agent from PaperOrchestra\n(Song et al., 2026, arXiv:2604.05018, §4 Step 2 and App. F.1 p.45).\n\n**Cost: ~20–30 LLM calls.** The paper uses PaperBanana (Zhu et al., 2026) as\nthe default backbone with a closed-loop VLM-critique refinement. This skill\nexpresses that loop in host-agent terms: you (the host agent) generate\nmatplotlib code with your own LLM, render via your Bash/Python tool,\noptionally critique the rendered PNG with your vision model, redraw, and\nfinally caption.\n\n## Inputs\n\n- `workspace/outline.json` — specifically the `plotting_plan` array\n- `workspace/inputs/idea.md` and `workspace/inputs/experimental_log.md` —\n  the source data\n- `workspace/inputs/figures/` — optional pre-existing figures (`PlotOn` mode)\n\n## Outputs\n\n- `workspace/figures/<figure_id>.png` — one PNG per `plotting_plan` entry\n  (300 DPI, sized to the requested aspect ratio)\n- `workspace/figures/captions.json` — `{figure_id: caption_text}` map\n\n## Workflow\n\n### Per figure (executed independently per `figure_id`)\n\n1. **Read the figure spec** from `outline.json`:\n   ```json\n   {\n     \"figure_id\": \"fig_main_results\",\n     \"title\": \"Main Results on Dataset X\",\n     \"plot_type\": \"plot\",\n     \"data_source\": \"experimental_log.md\",\n     \"objective\": \"Visual summary (Grouped Bar Chart) demonstrating ...\",\n     \"aspect_ratio\": \"5:4\"\n   }\n   ```\n\n2. **Few-shot retrieval (visual planning)**: pick the matching pattern from\n   `references/chart-patterns.md` (for `plot_type==\"plot\"`) or\n   `references/diagram-patterns.md` (for `plot_type==\"diagram\"`).\n\n3. **Extract data**: parse `idea.md` and/or `experimental_log.md`\n   (`data_source` field tells you which) to obtain the numeric values or\n   conceptual entities the figure needs. For `experimental_log.md`, the\n   `## 2. Raw Numeric Data` section contains markdown tables.\n\n4. **Render**:\n\n   **If `PAPERBANANA_PATH` is set** — use the PaperBanana backbone\n   (Zhu et al., 2026). It runs a Retriever → Planner → Stylist → Visualizer\n   → Critic loop and is especially good for `plot_type == \"diagram\"`.\n   See `references/paperbanana-cookbook.md` for setup (needs a Gemini API key).\n\n   ```bash\n   python skills/plotting-agent/scripts/paperbanana_render.py \\\n       --figure-id <figure_id> \\\n       --caption   \"<objective from figure spec>\" \\\n       --content-file workspace/inputs/idea.md \\\n       --task      <diagram|plot> \\\n       --aspect-ratio <aspect_ratio> \\\n       --out       workspace/figures/<figure_id>.png\n   ```\n\n   **Otherwise** — write a matplotlib script and run it via your Bash tool,\n   or use the bundled helper:\n   ```bash\n   python skills/plotting-agent/scripts/render_matplotlib.py \\\n       --spec spec.json \\\n       --out workspace/figures/<figure_id>.png\n   ```\n   The script must apply the academic style from `chart-patterns.md`, use the\n   correct pixel size from `aspect-ratios.md`, save at 300 DPI, and call\n   `plt.close()` after `savefig`.\n\n5. **VLM critique loop (optional, only if your host has vision)**:\n   - Reload the rendered PNG as a multimodal input to your LLM.\n   - Critique it against the figure's `objective` from the outline. Look for:\n     visual artifacts, mislabeled axes, illegible text, color clashes,\n     misleading scaling, missing legend, overlapping labels.\n   - If problems are found, regenerate the matplotlib script with corrections\n     and re-render. Cap at 3 critique iterations per figure.\n   - This is the closed-loop refinement step the paper inherits from\n     PaperBanana. See `references/plotting-pipeline.md` for the full loop\n     description.\n   - **If your host has no vision input, skip this step entirely.** The\n     figure will still render correctly, just without iterative refinement.\n\n6. **Generate the caption** using the verbatim Caption Generation prompt at\n   `references/caption-prompt.md`. Inputs to the caption prompt:\n   - `task_name` — the section the figure belongs to (e.g., \"Methodology\",\n     \"Experiments\")\n   - `raw_content` — the surrounding section text (or content_bullets from\n     the section_plan if the section isn't drafted yet)\n   - `description` — the `objective` field from the figure spec\n   - `figure_desc` — a 1-sentence description of what the rendered figure\n     actually shows (from your VLM critique pass, or from the script's plan\n     if no vision)\n\n   Write the caption to `workspace/figures/captions.json` keyed by\n   `figure_id`. **Captions must NOT contain `Figure N:` or `Caption N:`\n   prefixes** — the LaTeX template handles numbering. Plain text only, no\n   markdown.\n\n## Conceptual diagrams\n\nFor `plot_type == \"diagram\"`, prefer PaperBanana when available — its\nRetriever grounds the Planner in real published paper diagrams.  If\n`PAPERBANANA_PATH` is unset, follow `references/diagram-patterns.md`.\nPatterns include block diagrams, system overviews, flowcharts, and\nalgorithm-as-graph. The bundled helper:\n\n```bash\npython skills/plotting-agent/scripts/render_diagram.py \\\n    --spec diagram_spec.json \\\n    --out workspace/figures/<figure_id>.png\n```\n\nhandles the simple cases (boxes-and-arrows). For complex Fig-1-style\noverview diagrams, write matplotlib patches code yourself.\n\n## Hard rules\n\n- **300 DPI** for every figure. Lower DPI gets rejected at the LaTeX compile\n  step on conference templates.\n- **Aspect ratio is exact**. The figure spec's `aspect_ratio` is one of 12\n  enumerated strings. Use the pixel targets in `references/aspect-ratios.md`.\n- **Hide top and right spines** for plots. (Diagrams: no spines at all.)\n- **Muted academic colors** only. The palette is in `chart-patterns.md`.\n  Never use matplotlib defaults (too saturated for print).\n- **No 3D, no pie charts, no decorative visuals.** The paper's evaluators\n  penalize these.\n- **Every figure MUST have a caption** in `captions.json`. The Section\n  Writing Agent will fail-stop if a caption is missing for any figure\n  referenced from the outline.\n- **No `Figure N:` prefix** in captions — LaTeX adds it.\n- **Never describe data you didn't plot.** The Plotting Agent must not\n  hallucinate axes, baselines, or trends. Source-of-truth is\n  `experimental_log.md` or `idea.md`.\n\n## Pre-existing figures (PlotOn mode)\n\nIf `workspace/inputs/figures/` is non-empty, check whether any pre-existing\nfile matches a `figure_id` in the outline (by filename prefix). If so,\n**copy** it into `workspace/figures/` as-is and **still generate a caption**\nusing the caption prompt. Only generate from scratch the figure_ids that\nhave no pre-existing counterpart.\n\n## Resources\n\n- `references/caption-prompt.md` — verbatim Caption Generation prompt from App. F.1\n- `references/plotting-pipeline.md` — the full few-shot → render → critique → caption loop\n- `references/chart-patterns.md` — matplotlib style + chart type recipes\n- `references/diagram-patterns.md` — conceptual diagram recipes\n- `references/aspect-ratios.md` — pixel targets for each of the 12 allowed ratios at 300 DPI\n- `references/paperbanana-cookbook.md` — **NEW** PaperBanana setup, usage, cost notes, attribution\n- `scripts/render_matplotlib.py` — render a JSON plot spec → PNG (matplotlib fallback)\n- `scripts/render_diagram.py` — render a JSON diagram spec → PNG (matplotlib fallback)\n- `scripts/paperbanana_render.py` — **NEW** PaperBanana backbone wrapper (reads `PAPERBANANA_PATH` from env)","author":"@Ar9av","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/Ar9av/PaperOrchestra/tree/main/skills/plotting-agent","license":"MIT","category":"document","lang":"en","tokens":1856,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"references/aspect-ratios.md","size":2094,"sha256":"ab4eff1a5f5cdf2b01765b6fa47c1f4b07e6e6d1ea7efe39347a746270e806c3"},{"path":"references/caption-prompt.md","size":2735,"sha256":"a9b7f4016a13f2ae40666b82de23d0bc2a52a479421e037091d9384c942747ab"},{"path":"references/chart-patterns.md","size":6732,"sha256":"d7bcb33896cd06a90d7c621804bd94d4a25ee8dc00d6227a439a6ec678f0adf5"},{"path":"references/diagram-patterns.md","size":3943,"sha256":"beb6ddb5750fe0c333c8310866512bbdf1ee9a25494d76f7c14826cc01d52510"},{"path":"references/paperbanana-cookbook.md","size":6122,"sha256":"c87a846b27f6e891a8e2d97ce91c4e686179d41182a855bc38c91babe0eb4c18"},{"path":"references/plotting-pipeline.md","size":5961,"sha256":"646b194420f29f8e1676ffc681a90ea1296655478da871d98cacdcf0586b5ec2"},{"path":"scripts/paperbanana_render.py","size":12987,"sha256":"49ae3bb263141b5ef9a00f587e0e3834d8e4663ce239a68493edfdf12af3748c"},{"path":"scripts/render_diagram.py","size":4225,"sha256":"ee343f45880c5bae541de49310ef821fa8f83753fb561d86b56e49add59d6917"},{"path":"scripts/render_matplotlib.py","size":7253,"sha256":"7df685330bcaa90f9f7e78950842f497f79d57ecf9c4baeabc52e43cb460378b"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[{"code":"net.endpoints","kind":"exfiltration","excerpt":"aistudio.google.com, openrouter.ai","message":"bundled scripts reach 2 external host(s)","severity":"warn"}],"scannedAt":"2026-08-22","hasScripts":true,"networkEndpoints":["aistudio.google.com","openrouter.ai"]}}