XY Plot: Render (lab)
The node that turns a batch run into a labeled grid
- xy_plot_data
- image
- plot_config_grid
- plot_config_header
- plot_config_footer
- grid
- image
XY Plot: Render (lab) is the payoff node. It sits at the end of your pipeline, takes each image as it comes out of generation, and once every image for a page has arrived, assembles them into a labeled grid. You don't stitch anything yourself, you don't count images - the node knows how many to expect because its sibling XY Plot: Queue (lab) told it.
If you've ever built a "compare 8 seeds" workflow by hand - eight KSamplers, eight preview nodes, manual screenshots - this is the escape hatch. Queue varies, render organizes, you read the answer off one grid.
How it works
The two nodes are joined by the special xy_plot_data wire: the queue sends processing state - current index, current page, which dim1/dim2 value this image corresponds to, and whether the batch is done. The render node accumulates every image into a pager keyed by grid position. Until a page is complete, the grid output is blocked (ComfyUI's ExecutionBlocker), so nothing downstream fires early on a half-empty grid - but the image output passes through every individual frame, so previews still flow.
When the page fills, it builds the grid with your headers and formatting and hands it over. With pagination configured in the queue, a new grid is produced per page - that's the grid output being a page, not "the final image."
The inputs that matter
- xy_plot_data - from
XY Plot: Queue. Non-negotiable; without it the node has no idea where images belong. - image - whatever your process generates per iteration.
- dim1_header_format / dim2_header_format - templates for the row/column headers, default
{dim1}/{dim2}. The{dim1}/{dim2}placeholders swap in the current value. This is where you make grids readable:CFG: {dim1}turns7.5intoCFG: 7.5. Use\nfor multiline. Pythonformat()syntax applies, so padding and truncation are available too. - direction - boolean:
true(default) shows dim1 values as rows, dim2 as columns; flip it and the grid transposes.
Optional config wires (plot_config_grid, plot_config_header, plot_config_footer) come from the pack's Plot Config nodes - gap size, background color (including a transparent RGBA mode for dropping your own background image under the grid), fonts, and page header/footer text. All optional; the default grid already looks decent.
Outputs: grid (the assembled page) and image (the current individual image, passed through untouched - handy if you also want to save every frame separately).
Install
ComfyLab Pack is one install for its whole family (the "(lab)" suffix marks its nodes). ComfyUI Manager: search ComfyLab Pack, install, restart.
cd ComfyUI/custom_nodes
git clone https://github.com/bugltd/ComfyLab-Pack.git
cd ComfyLab-Pack
pip install -r requirements.txt
Restart after. No model downloads; requirements are light (opencv-python, pyyaml, jsonschema and a few small ones).
Gotchas
- Grid stays blocked if a run dies early. An error partway through the batch means that page never completes and
gridnever fires. Fix the failing iteration and rerun - the queue resets cleanly. - Rows vs columns is only decided here. You choose the layout at render time, not when wiring the queue. That's the feature, not a bug.
- Huge grids get unreadable. If you're plotting 10×10, consider pagination in the queue (
max_dim1_per_page,max_dim2_per_page) so each page is a sane size.
The one-liner: queue decides what order things generate, render decides how they look together. Between them they'll do the thing you currently screenshot into a collage manually.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| xy_plot_data | XY_PLOT_DATA | data sent by the queue, to indicate the cuttent state of processing | |
| image | IMAGE | — | |
| dim1_header_format | STRING | {dim1} | template text to be displayed as dim1 header. the '{dim1'} placeholder will be replaced by the current value. Use '\n' for multiline text. |
| dim2_header_format | STRING | {dim2} | template text to be displayed as dim2 header. the '{dim2'} placeholder will be replaced by the current value. Use '\n' for multiline text. |
| direction | BOOLEAN | true | display dim1 values as rows or columns |
| plot_config_gridopt | PLOT_CONFIG_GRID | optional: plot configuration for the grid | |
| plot_config_headeropt | PLOT_CONFIG_HF | optional: plot configuration for the page header | |
| plot_config_footeropt | PLOT_CONFIG_HF | optional: plot configuration for the page footer |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| grid | IMAGE | grid page |
| image | IMAGE | individual image, as received in input |