# How the X/Y/Z Plot Feature Works in AUTOMATIC1111: Systematic Parameter Comparison

> Discover how the X/Y/Z plot feature in AUTOMATIC1111 compares generation parameters systematically by varying up to three settings across a grid and processing all combinations.

- Repository: [AUTOMATIC1111/stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui)
- Tags: deep-dive
- Published: 2026-02-24

---

**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`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/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`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/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.

```python
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`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/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 `StableDiffusionProcessing` instance (`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

```python
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`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/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:

1. Creates a shallow copy of the base `StableDiffusionProcessing` object `p`
2. Applies the three axis values using their respective `AxisOption.apply` methods
3. Adjusts seeds if the "vary seeds for X/Y/Z" options are enabled
4. Calls `process_images(pc)` from `modules/processing` to 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`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/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.

```python
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:

1. Select **"X/Y/Z plot"** from the Scripts dropdown in the txt2img or img2img tab
2. Choose parameter types for the X, Y, and Z axes (e.g., **CFG Scale**, **Steps**, **Sampler**)
3. Enter values using range syntax (`20-30`), CSV lists (`5,6,7,8`), or click the **Fill** button to populate all available choices
4. Configure display options: **Draw legend**, **Include sub-grids**, **Vary seeds**, and **Margin size**
5. 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:

```python
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.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/scripts/xyz_grid.py) as a `Script` subclass that registers automatically with the WebUI via the `title()` method
- **AxisOption** objects define configurable parameters including type conversion, application logic via `apply_field`, and validation via `confirm` functions
- Input parsing supports integer ranges, step-based float ranges (`1-10[5]`), and CSV lists through the `process_axis` function
- Cost-based loop ordering places expensive parameters (like checkpoint changes) in outer loops to minimize model reloading overhead
- The `cell` function processes each grid coordinate by mutating a copy of the `StableDiffusionProcessing` object and invoking `process_images`
- Final grids are assembled using `draw_xyz_grid`, which composites sub-grids and adds legends via `image_grid` and `draw_grid_annotations` from [`modules/images.py`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/modules/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`](https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/main/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.