Nodes/ComfyUI-Testing/XYZ Plot (Artify)
ComfyUI Node

XYZ Plot (Artify)

XYZ Plot (Artify)

By ArtifyGames·Created 7 months ago·Updated 4 days ago· 0
XYZ Plot (Artify)
  • images
  • xyz_plot
output_folder_name%date:yyMMdd%_X_%inputx_node_title%_%inputx_widget_name%_Y_%inputy_node_title%_%inputy_widget_name%_Z_%inputz_node_title%_%inputz_widget_name%
input_xnone
value_x6.5; 7.0; 7.5
input_ynone
value_y20; 30; 40
input_znone
value_zEuler; Heun

XYZ plots are how you answer "does Euler vs. Heun actually matter at this CFG?" without guessing. In Automatic1111 and Forge they're a built-in script; in ComfyUI you have to bring your own, and the classics are the Efficiency Nodes XY Plot and the core X/Y/Z Plot. This one's pitch is different: no converting widgets to inputs, no typing a target node's ID. XYZ Plot (Artify) gives you dropdowns populated live from the widgets already sitting in your graph - you pick what to sweep, drop in the values, and it queues the whole grid for you.

It's a young pack (basically zero community footprint as of this writing), so expect a couple of rough edges, but the core idea is sound and it saves real time on sampler/CFG/LoRA-strength comparisons.

How it works

The trick is a two-stage run. First, a bit of frontend JS scans every node on the canvas and builds a reference for each widget that looks like #12::KSampler::cfg. That reference is what lands in input_x/input_y/input_z - which is why the dropdowns only show widgets, not node IDs you have to look up.

On the first run, the node:

  1. Splits value_x/value_y/value_z on semicolons.
  2. Writes result.json plus a workflow.json into ComfyUI/output/<folder_name>.
  3. Deep-copies the prompt for every combination, overwrites the chosen widget with the next value, and re-queues each cell as a separate partial-execution job via the local /prompt endpoint - one queue entry per grid cell.

Each queued cell re-executes the plot node in "cell mode," sees the x/y/z index tucked into its inputs, and saves that single image as something like x2_y4_1.jpeg. If a folder with the same name already exists, it gets moved to _old_<timestamp> first rather than merged - archiving is always-on and you can't turn it off.

The inputs that matter

  • input_x / input_y (required): dropdowns of every widget on your other nodes. Pick e.g. a KSampler's sampler_name and cfg.
  • value_x / value_y / value_z: multiline strings, semicolon-separated. 6.5; 7.0; 7.5 for CFG, Euler; Heun for samplers.
  • input_z / value_z (optional): leave input_z at none and value_z empty if you don't want a Z axis - you'll get an error if you fill values but don't pick a target.
  • output_folder_name: supports tokens like %date:yyMMdd%, %inputx_node_title%, %inputx_widget_name%. The default is verbose but genuinely useful.
  • images: wire this from your VAE decode so the node has something to save.

The one output, xyz_plot (type ARTIFY_XYZ_PLOT), plugs into XYZ Viewer (Artify).

Install

The pack is tiny and dependency-free - requirements.txt is effectively empty, no models to download.

cd ComfyUI/custom_nodes
git clone https://github.com/ArtifyGames/comfyui-testing.git

Restart ComfyUI and refresh the browser tab. Or use ComfyUI Manager and search for comfyui-testing (pack title "ComfyUI-Testing").

Where people get burned

  • Empty dropdowns: they're populated from the live graph, and the node excludes itself - the node you want to sweep has to exist on the canvas first.
  • Z error out of nowhere: if you leave input_z on none, clear value_z. The node throws value_z was provided, but input_z is not selected otherwise.
  • Combo widgets: if you sweep a sampler or scheduler combo, the values have to be real option names. Free-text and number widgets are the safest targets.
  • Queue spam: a 3×3 sweep is 9 queue entries plus the initial run. Bigger grids bury your queue - that's by design, since each cell is a separate render with its own seed handling.

If the wrong cells keep coming out, double-check that the node title or widget you selected still exists - the reference is re-resolved on every run, so renaming a target node can break the ref and raise Widget '...' was not found on node #....

CategoryArtify/Testing

Inputs (8)

NameTypeDefaultDescription
imagesIMAGE
output_folder_nameSTRING%date:yyMMdd%_X_%inputx_node_title%_%inputx_widget_name%_Y_%inputy_node_title%_%inputy_widget_name%_Z_%inputz_node_title%_%inputz_widget_name%
input_xCOMBOnone1 options: none
value_xSTRING6.5; 7.0; 7.5
input_yCOMBOnone1 options: none
value_ySTRING20; 30; 40
input_zoptCOMBOnone1 options: none
value_zoptSTRINGEuler; Heun

Outputs (1)

NameTypeDescription
xyz_plotARTIFY_XYZ_PLOT