How the X/Y/Z Plot Feature Works in AUTOMATIC1111: Systematic Parameter Comparison
The X/Y/Z plot feature in AUTOMATIC1111’s WebUI is a built-in Python script that varies up to three generation parameters simultaneously across a Cartesian grid, processes every combination via the standard process_images pipeline, and composites the results into annotated image matrices using the grid utilities in modules/images.py.
The X/Y/Z plot (commonly called the XYZ grid) is a comprehensive parameter sweeping tool integrated into the AUTOMATIC1111/stable-diffusion-webui repository for comparing Stable Diffusion hyperparameters. Implemented entirely in scripts/xyz_grid.py, this feature enables systematic exploration of how changes to CFG scale, sampling steps, seeds, or model checkpoints affect output quality by automating the generation of multi-dimensional image grids.
Script Architecture and UI Integration
The X/Y/Z plot is implemented as a Script subclass that hooks into the WebUI’s extension system. The Script.title() method returns the exact string "X/Y/Z plot", which the UI uses to identify and list the script in the Scripts dropdown menu.
class Script(scripts.Script):
def title(self):
return "X/Y/Z plot"
The ui(is_img2img) method constructs the Gradio interface dynamically, creating dropdowns for axis selection, textboxes for value input, and ToolButton widgets (from modules/ui_components) for auxiliary functions like auto-filling values or swapping axes. These controls bind to helper functions including fill, select_axis, and change_choice_mode to manage visibility and content updates.
AxisOption Structure and Parameter Definitions
Each variable parameter is defined as an AxisOption object stored in the axis_options list at the top of scripts/xyz_grid.py. These objects encapsulate the complete logic for a sweepable parameter:
- label: Display name in the UI dropdown (e.g., "CFG Scale")
- type: Data conversion function (
int,float,str_permutations) - apply: A callable that mutates the
StableDiffusionProcessinginstance (p) for a given value - format_value: Formatter for grid legend annotations (e.g.,
"CFG Scale: 7.5") - confirm: Optional validator to ensure values exist (e.g., verifying checkpoint names)
- choices: Static list or callable returning valid options for dropdown modes
axis_options = [
AxisOption("Seed", int, apply_field("seed")),
AxisOption("CFG Scale", float, apply_field("cfg_scale")),
AxisOption("Sampler", str, apply_field("sampler_name"), choices=lambda: [...]),
]
Execution Pipeline and Grid Generation
Parsing Input Values and Range Expansion
When generation begins, the Script.run() method calls process_axis (lines ~558-620) to parse the input value strings. This function handles multiple syntaxes: integer ranges (1-5 expands to [1,2,3,4,5]), float ranges with step counts (1-10[5] generates five evenly spaced values via NumPy), CSV lists, and permutation strings.
Cost-Based Iteration Optimization
To minimize expensive operations like model checkpoint reloading, the script analyzes each axis’s cost property. The axis with the highest computational cost becomes the outermost loop (processed first), ensuring resource-heavy parameters change least frequently. This optimization logic appears around lines 884-904 in scripts/xyz_grid.py.
Cell Processing and Image Generation
For each coordinate in the 3D grid, the script invokes the nested cell(x, y, z, ix, iy, iz) function. This function:
- Creates a shallow copy of the base
StableDiffusionProcessingobjectp - Applies the three axis values using their respective
AxisOption.applymethods - Adjusts seeds if the "vary seeds for X/Y/Z" options are enabled
- Calls
process_images(pc)frommodules/processingto execute the standard generation pipeline
Grid Composition with draw_xyz_grid
After all cells complete, the draw_xyz_grid function (starting at line ~887) assembles the final output. It allocates a 3D results matrix, creates sub-grids for each Z-slice using images.image_grid from modules/images.py, and generates legend annotations via images.draw_grid_annotations. The function manages margin sizing, sub-grid inclusion, and CSV export mode based on user options.
processed = draw_xyz_grid(
p,
xs=xs, ys=ys, zs=zs,
x_labels=[x_opt.format_value(p, x_opt, x) for x in xs],
y_labels=[y_opt.format_value(p, y_opt, y) for y in ys],
z_labels=[z_opt.format_value(p, z_opt, z) for z in zs],
cell=cell,
draw_legend=draw_legend,
include_lone_images=include_lone_images,
include_sub_grids=include_sub_grids,
margin_size=margin_size
)
Practical Usage Guide
To use the X/Y/Z plot feature in the AUTOMATIC1111 WebUI:
- Select "X/Y/Z plot" from the Scripts dropdown in the txt2img or img2img tab
- Choose parameter types for the X, Y, and Z axes (e.g., CFG Scale, Steps, Sampler)
- Enter values using range syntax (
20-30), CSV lists (5,6,7,8), or click the Fill button to populate all available choices - Configure display options: Draw legend, Include sub-grids, Vary seeds, and Margin size
- Click Generate to produce the composite grid showing all parameter combinations
Programmatic Access
Developers can invoke the script programmatically by instantiating the Script class and calling run() with a configured StableDiffusionProcessing object:
from scripts.xyz_grid import Script
xyz = Script()
result = xyz.run(
p, # Base StableDiffusionProcessing object
x_type=4, x_values="5,6,7", x_values_dropdown=[],
y_type=3, y_values="10-30[5]", y_values_dropdown=[],
z_type=9, z_values="Euler a,DDIM", z_values_dropdown=[],
draw_legend=True,
include_lone_images=False,
include_sub_grids=False,
no_fixed_seeds=False,
vary_seeds_x=False,
vary_seeds_y=False,
vary_seeds_z=False,
margin_size=0,
csv_mode=True
)
The returned Processed object contains the composite grid images in result.images and generation metadata in result.infotexts.
Summary
- The X/Y/Z plot is implemented in
scripts/xyz_grid.pyas aScriptsubclass that registers automatically with the WebUI via thetitle()method - AxisOption objects define configurable parameters including type conversion, application logic via
apply_field, and validation viaconfirmfunctions - Input parsing supports integer ranges, step-based float ranges (
1-10[5]), and CSV lists through theprocess_axisfunction - Cost-based loop ordering places expensive parameters (like checkpoint changes) in outer loops to minimize model reloading overhead
- The
cellfunction processes each grid coordinate by mutating a copy of theStableDiffusionProcessingobject and invokingprocess_images - Final grids are assembled using
draw_xyz_grid, which composites sub-grids and adds legends viaimage_gridanddraw_grid_annotationsfrommodules/images.py
Frequently Asked Questions
What file contains the X/Y/Z plot implementation in AUTOMATIC1111?
The complete implementation resides in scripts/xyz_grid.py within the AUTOMATIC1111/stable-diffusion-webui repository. This file contains the Script class definition, the axis_options configuration table, the draw_xyz_grid composition logic, and all UI helper functions including process_axis and cell.
How does the X/Y/Z plot handle different parameter types like seeds versus samplers?
Each parameter type is encapsulated in an AxisOption object that specifies a type converter (e.g., int for seeds, str for samplers) and an apply function that modifies the StableDiffusionProcessing object. Samplers and checkpoints utilize choice lists validated by confirm functions, while numeric parameters support range syntax parsed by process_axis using NumPy interpolation.
Why does the X/Y/Z plot change the iteration order for some parameters?
The script implements cost-based optimization to minimize resource-intensive operations. Parameters with high computational costs—such as changing model checkpoints or VAEs—are moved to the outermost loops (processed first), ensuring they change least frequently. This reduces redundant model reloading and improves generation efficiency.
Can I use range syntax like "10-20[3]" in the X/Y/Z plot values?
Yes. The process_axis function interprets range expressions where 10-20 expands to all integers in that range, while 10-20[3] generates three evenly spaced values between 10 and 20 using NumPy's interpolation. The feature also supports explicit CSV values and permutation strings for combinatorial testing.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →