D2 XY Grid Image
The node that turns an XY plot run into one labeled comparison grid
- images
- x_annotation
- y_annotation
- grid_pipe
- images
- memo
An XY plot run produces a pile of images. D2 XY Grid Image is the node that catches that pile and glues it into a single labeled grid - rows for one axis, columns for the other, with the axis titles written in. It's the payoff node of the D2 XY Plot family: without it, you'd be opening 12 or 20 files and mentally reconstructing which one was which. With it, you get one image that says everything at a glance.
How it works
It's a stateful collector, which is the unusual part for a ComfyUI node. Each time the plot fires, this node receives one image and accumulates it into an internal batch. The plot sends a status signal through the grid_pipe - INIT on the first run (reset the buffer), empty string while collecting, and FINISH on the last run. Only when FINISH arrives does it assemble the whole batch into a grid and output it. During collection it can pass the individual images through (grid_only off) or hold them back (grid_only on, the default).
The grid_pipe from D2 XY Plot or D2 XY Plot Easy carries everything it needs - the x_annotation, y_annotation, and the status - so wiring is literally one cable: plot's grid_pipe → this node's grid_pipe. It also accepts the annotations and status as separate inputs if you're driving it manually.
The inputs you'll touch
images- the incoming per-run image. Wire this to your sampler's IMAGE.grid_pipe- one wire from the plot. Preferred over the individual inputs.font_size/grid_gap- header size and gap between cells. Defaults are sane (24 / 0).swap_dimensions- flips the grid orientation when your X/Y axes are visually backwards.draw_x_label/draw_y_label- toggle the axis headers on and off.grid_only- true (default) outputs just the final grid; false also passes each individual image through.
There are two outputs. images is the assembled grid. memo is a newer addition and arguably underrated: it outputs a text list of the grid's parameters (formatted like "X: positive / black hair, / blonde hair,"). It's designed to feed memo_text on D2 Save Image Eagle, so your comparison grid lands in Eagle with a full description of what it compared - no more wondering which grid was the CFG test three weeks later.
Where it goes wrong
The classic failure is forgetting the status wire. If you connect images and the annotations but not grid_pipe/status, the node never sees FINISH, so it accumulates forever and you never get a grid. The status input is a STRING socket - if you're building the plot manually, that's the signal you must drive.
A second trap: grids need the plot to actually run to completion. If auto_queue is off and you stop after a few rows, the buffer just sits there holding partial data until you reset. Use the plot's Reset index button before a fresh run, or the grid will layer a new run's images on top of the old ones.
Installing
Part of D2 Nodes ComfyUI:
cd ComfyUI/custom_nodes
git clone https://github.com/da2el-ai/D2-nodes-ComfyUI
or search "D2 Nodes ComfyUI" in ComfyUI Manager. No model downloads; the only real requirement is a recent ComfyUI (V3 schema, since the pack's v32.0.0).
If you're doing any amount of parameter testing, this node is why the D2 XY family is worth installing in the first place. The grid is the deliverable; everything else is setup.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| font_size | INT | 24 | — |
| grid_gap | INT | 0 | — |
| swap_dimensions | BOOLEAN | false | — |
| grid_only | BOOLEAN | true | — |
| draw_x_label | BOOLEAN | true | — |
| draw_y_label | BOOLEAN | true | — |
| x_annotationopt | D2_TAnnotation | — | |
| y_annotationopt | D2_TAnnotation | — | |
| statusopt | STRING | — | |
| grid_pipeopt | D2_TGridPipe | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| memo | STRING | — |