Aurora Lab / Skills / Figure Editor

Figure Editor

Multi-panel journal figures from the images you already have. Your agent inspects every panel, lays them out at an exact column width with a, b, c labels, keeps a slot for panels you haven't made yet, tells you which ones won't print sharply, and drafts the caption.

  • v1.1.0
  • Python 3.10+ · matplotlib, Pillow, numpy
  • No network access
  • Works with any SKILL.md agent

Overview

The last step before submission is often the fiddliest: five panels exported from three scripts and a microscope, all at different sizes, that have to become one figure at exactly 183 mm wide with matching labels. Figure Editor turns your agent into a careful figure assembler that:

  • Inspects before it proposes. Pixel size, aspect ratio and DPI tag of every panel, then a layout suggestion with its reason.
  • Lays panels out for the page. Grids, rows, spanning panels, and justified rows that give mixed portrait and landscape panels one height per row with no gaps.
  • Prints at an exact width, so the label size you ask for is the size that gets printed.
  • Keeps a slot for missing panels: a grey "Data not available" box in the right place.
  • Checks print resolution and shrinking text, and says exactly how many pixels each weak panel needs. It never upscales.
  • Drafts the caption after looking at every panel, leaving what it can't see in [brackets].

Figure Editor or Paper Figures? Paper Figures designs and draws figures from your data. Figure Editor assembles images that already exist (plots, micrographs, gels, diagrams, panels made by Paper Figures or anything else) into one labelled multi-panel figure. Each works on its own; they pair well.

Quick start

  1. Get the skill from Agensi and add it to your agent (Claude Code, Codex CLI, Cursor, Gemini CLI or any agent that loads SKILL.md skills).
  2. Have Python 3.10+ with matplotlib, Pillow and numpy in the project's environment. The assembly script ships inside the skill; nothing else to install.
  3. Ask in plain words.

Example requests:

  • "Put research/figures/a.png, b.png and c.png into one figure. No layout preference."
  • "Make a 2x2 figure from these four images for a single-column slot, lowercase labels."
  • "Assemble Figure 3; panel B isn't ready yet, leave a placeholder."
  • "Why does panel C look blurry in my assembled figure?"

Reading layout names. Grids are columns x rows: 2x1 grid puts two panels side by side, 1x2 grid stacks them vertically, 3x2 grid is three across and two down. N+M strings give the number of panels in each row: 1+2 is one full-width panel on top and two below.

How it works

  1. Intake. One message with two questions: which images, in which order, and whether you have a layout, width and label style in mind. If you describe a panel instead of giving a path, the agent asks which file it is; it never guesses a path.
  2. Inspect. assemble_figure.py --inspect prints each panel's size, aspect ratio and DPI tag and a suggested layout. The agent explains its proposal, and if one would make the figure too tall for a page it says so and proposes another (in the demo: 117 mm instead of 253 mm).
  3. Placeholders. A missing panel becomes a grey box labelled with its letter, in its slot. The agent says so, and reminds you to replace it.
  4. Assemble. One command writes the figure at the exact width, with labels at true print size. PDF output embeds each raster panel without resampling.
  5. Look, then report. The agent opens a freshly rendered preview to check order, labels, clipping and stretching, then explains every warning in plain language with the fix.
  6. Caption. It opens every panel image, fills the caption draft with complete sentences about what is visible, and reuses any <panel>.md caption notes found next to an image.

Layouts

Layout string Result
2x2 grid 2 columns x 2 rows, filled left to right, top to bottom
2x1 grid / 1x2 grid two side by side / two stacked
1+2, 2+3, 1+2+3 panels per row; widths divide evenly
3x2 grid Panel A full width panel A spans the top row; the rest flow around it
--fit rows justified rows: one height per row, widths follow each panel's shape

Checks it runs

Warning What it means
Low resolution The panel's effective dpi at its printed size is below the threshold (300 by default, --min-dpi to change). The warning gives the pixel width needed.
Printed at N% of native size The panel was shrunk to fit, so its own text and lines shrink too (8 pt at 66% is about 5.3 pt).
DPI metadata differs Panels were exported with inconsistent settings. Usually harmless on its own.
16-bit image scaled to 8-bit Display contrast was set from the data's range.
Vector panel rasterised PDF/SVG panels become pixels (600 dpi) in the assembly.
Figure is N mm tall Taller than most journal pages allow (about 240 mm).

The resolution, text-size and height checks are automatic. Choosing the layout, checking the preview and writing the caption are steps the agent carries out and reports.

Files it reads and writes

Path
Reads the image files you name (PNG, TIFF, JPEG, PDF, SVG), e.g. in research/figures/, and any <panel>.md caption note next to them
Writes the figure you name (.pdf recommended; .png, .tif, .svg, .eps, .jpg also work) and its caption draft <name>.md in research/figures/
Elsewhere outside research/figures/ the draft is <name>_captions.md next to the figure

It never modifies, moves or overwrites an input image (it refuses to write over one), and never overwrites an existing caption draft unless asked, so your edits survive a rebuild. The caption draft also records each panel's printed size and effective dpi, every warning, and the exact command to rebuild the figure.

Command line

Your agent runs this for you. assemble_figure.py is a single self-contained file: it runs from the skill's scripts/ folder or with the file on standard input (python - --inspect a.png b.tif), and writes only the figure and caption draft you name.

python figure-editor/scripts/assemble_figure.py --inspect a.png b.tif c.png
python figure-editor/scripts/assemble_figure.py a.png b.tif none d.png \
    --layout "2x2 grid" --width double --labels lower -o research/figures/fig1.pdf
Option Purpose
--layout grid, rows or spanning layout (see above); omitted = automatic
--fit grid (aligned columns) or rows (justified rows for mixed shapes)
--width single (89 mm), onehalf (120 mm), double (183 mm, default), or e.g. 180mm, 7in
--labels upper (A, B), lower (a, b), plain or none
--font-size label size in pt at printed size (default 10)
--dpi, --min-dpi raster output resolution; resolution warning threshold (both default 300)
--span A=2x2 in a grid layout, panel A covers 2 columns x 2 rows (A=2: two columns)
--panel-label "C=B'" a custom label for one panel
none in place of a path: a placeholder panel

Optional: PDF and SVG panels

PNG, TIFF (including 16-bit and multi-page) and JPEG panels work out of the box. PDF and SVG panels are rasterised at 600 dpi, which needs one optional tool: the pymupdf package (PDF and SVG), or poppler's pdftoppm command (PDF only). Without either, the panel becomes a placeholder with a warning and the agent asks you to export it as PNG or TIFF. Because these panels become pixels, an assembled figure is not fully vector; if your venue wants vector line art, assemble the original vector panels in a vector editor or LaTeX.

Journal sizes

The skill carries a reference table it reads when you name a venue. These values were checked against the publishers' own artwork pages in October 2026:

Publisher Widths (single · 1.5 · double) Resolution at final size
Nature 89 · 120–136 · 183 mm photos ≥ 300 dpi; line art as vector
Elsevier 90 · 140 · 190 mm 300 / 500 / 1000 dpi (halftone / combination / line art)
IEEE 88.9 · – · 182 mm > 300 dpi colour/greyscale, > 600 dpi line art

Cell Press and PNAS are listed with commonly quoted values (about 85 mm single and 174–178 mm double column). Journals within a publisher can differ and guides change, so confirm against your venue's current author guidelines before submission.

The research/ folder

Figure Editor works on its own. If you keep your project in a research/ folder, it uses the same plain-file convention as the other Aurora Lab research skills, so they cooperate without calling each other. Panels in research/figures/ (with an optional <panel>.md caption note from whatever made the panel) go in, and the assembled figure and its caption draft come out in the same folder.

FAQ

How is this different from Paper Figures?

Paper Figures designs and draws figures from your data. Figure Editor assembles finished images into one multi-panel figure with layout, labels, placeholders, resolution checks and a caption draft. They work well together, but neither needs the other.

What do I need installed?

Python 3.10+ with matplotlib, Pillow and numpy. Optionally pymupdf or poppler's pdftoppm for PDF/SVG panels. No network access.

Will it fix a blurry panel?

No. It reports the panel's effective dpi and the pixel width it needs, and suggests re-exporting from the source. Upscaling adds no detail, so it never does it.

Does it check against my journal's rules?

It checks resolution, shrinking text and figure height automatically, with an adjustable threshold. The reference table covers Nature, Elsevier and IEEE plus typical values for others. Confirm with your journal's current guidelines.

Can I change the figure later?

Yes. The caption draft records the exact command that built the figure. Replace a file, or swap none for the finished panel, and ask your agent to run it again; your caption edits are kept.

Does it work through Agensi's MCP connection, without a skill folder?

Yes. Your agent loads the instructions and the script on request, runs the script in-session and writes only the figure and its caption draft into your project. No skill file is copied into your project. Version 1.1 was tested this way.

Do I need the other Aurora Lab skills?

No. They share the research/ folder convention if you want to use them together.

Limitations

  • It assembles existing images. It does not make plots from data, edit pixels inside a panel, or invent content for a missing panel.
  • PDF and SVG panels are rasterised at 600 dpi, so the result is not fully vector. They also need PyMuPDF or poppler's pdftoppm.
  • Journal values are a starting point; confirm against your venue's current author guidelines.
  • The caption is a draft for you to complete: details that are not visible in the images stay in [brackets].

Changelog

1.1.0 · October 2026 · Works when the skill is delivered without a local folder (Agensi's MCP connection): the bundled panelkit library is merged into assemble_figure.py, one self-contained script that runs in-session and writes only the figure and its caption draft. It draws the same figures as 1.0, byte for byte. Spans and custom labels are now command-line options (--span, --panel-label) instead of a Python API, and no skill file is copied into your project. The rebuild command in the caption draft never carries --overwrite-captions, so re-running it keeps your caption edits.

1.0.0 · October 2026 · First release.