Files
Artificial-Sweetener-Simple…/tests/test_regional_multidiffusion_sampling.py
T
Artificial Sweetener f863fcf645 feat(nodes): add VAE options and clone-safe diffusion
Add VAE encode/decode option nodes across legacy and Comfy v3 exports, with tooltip and registration coverage. Preserve cloned model graph composition for differential diffusion in tiled and regional sampling paths.
2026-05-25 13:40:36 -04:00

976 lines
32 KiB
Python

# SimpleSyrup - workflow-focused ComfyUI extensions for image generation
# Copyright (C) 2026 Artificial Sweetener and contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Tests for regional MultiDiffusion sampling runtime."""
from __future__ import annotations
from types import SimpleNamespace
from typing import Any, cast
import pytest
import torch
from simple_syrup.domain.regional_detailing import LatentBox, LatentRegion
from simple_syrup.domain.segs import CropRegion
from simple_syrup.runtime import (
regional_multidiffusion_sampling,
sampling_samplers,
sampling_schedulers,
)
from simple_syrup.runtime.detail_previews import DetailPreviewContext
comfy_sample = regional_multidiffusion_sampling._comfy_sample()
comfy_utils = regional_multidiffusion_sampling._comfy_utils()
latent_preview = regional_multidiffusion_sampling._latent_preview()
def _preview_context() -> DetailPreviewContext:
"""Return a minimal regional detail preview context."""
return DetailPreviewContext(
image=torch.ones((1, 8, 8, 3), dtype=torch.float32),
work_region=CropRegion(2, 2, 6, 6),
work_mask=torch.ones((8, 8), dtype=torch.float32),
sampled_region=CropRegion(0, 0, 8, 8),
)
def test_sampling_callback_uses_generic_preview_without_detail_context(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Standalone regional runtime calls keep generic latent previews."""
monkeypatch.setattr(
latent_preview,
"prepare_callback",
lambda _model, _steps: "generic callback",
)
assert (
regional_multidiffusion_sampling._sampling_callback(FakeModel(), 4, None)
== "generic callback"
)
def test_sampling_callback_uses_detail_preview_with_context(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Detailer regional sampling uses the shared detail preview callback."""
context = _preview_context()
calls: dict[str, object] = {}
def fake_prepare_detail_preview_callback(
model: FakeModel,
steps: int,
preview_context: DetailPreviewContext,
) -> str:
"""Record detail preview callback preparation."""
calls["model"] = model
calls["steps"] = steps
calls["preview_context"] = preview_context
return "detail callback"
monkeypatch.setattr(
regional_multidiffusion_sampling,
"prepare_detail_preview_callback",
fake_prepare_detail_preview_callback,
)
model = FakeModel()
assert (
regional_multidiffusion_sampling._sampling_callback(model, 4, context)
== "detail callback"
)
assert calls == {"model": model, "steps": 4, "preview_context": context}
class FakeModel:
"""Provide the ModelPatcher methods used by the runtime."""
def __init__(
self,
model_options: dict[str, Any] | None = None,
parent: FakeModel | None = None,
) -> None:
"""Create a fake model patcher."""
self.load_device = torch.device("cpu")
self.model_options = {} if model_options is None else model_options
self.calc_wrapper: Any = None
self.model_sampling = object()
self.parent = parent
self.clone_count = 0
def clone(self) -> FakeModel:
"""Return a cloned model with copied options."""
self.clone_count += 1
return FakeModel(self.model_options.copy(), parent=self)
def set_model_sampler_calc_cond_batch_function(self, wrapper: object) -> None:
"""Capture the installed calc-cond-batch wrapper."""
self.calc_wrapper = wrapper
self.model_options["sampler_calc_cond_batch_function"] = wrapper
def set_model_denoise_mask_function(self, denoise_mask_function: object) -> None:
"""Capture the installed denoise-mask function."""
self.model_options["denoise_mask_function"] = denoise_mask_function
def get_model_object(self, name: str) -> object:
"""Return the requested fake model object."""
assert name == "model_sampling"
return self.model_sampling
class FakeSampler:
"""Represent a resolved sampler in tests."""
def sample(self, *args: object, **kwargs: object) -> object:
"""Provide ComfyUI's sampler protocol."""
del args, kwargs
return None
def test_clone_model_installs_regional_calc_cond_batch_wrapper() -> None:
"""The runtime clones the model and installs a regional wrapper."""
model = FakeModel()
wrapped_model, summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
model,
latent_width=8,
latent_height=4,
latent_ndim=4,
regions=(_region(0, 0, 4, 4, "positive", latent_width=8),),
)
)
assert wrapped_model is not model
assert isinstance(
wrapped_model.calc_wrapper,
regional_multidiffusion_sampling.RegionalMultiDiffusionCalcCondBatch,
)
assert summary.region_count == 1
def test_clone_model_composes_differential_on_same_clone() -> None:
"""Differential diffusion is installed without cloning a temporary parent."""
model = FakeModel()
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
model,
latent_width=8,
latent_height=4,
latent_ndim=4,
regions=(_region(0, 0, 4, 4, "positive", latent_width=8),),
differential_diffusion=True,
)
)
assert model.clone_count == 1
assert wrapped_model.parent is model
assert callable(wrapped_model.model_options["denoise_mask_function"])
assert isinstance(
wrapped_model.calc_wrapper,
regional_multidiffusion_sampling.RegionalMultiDiffusionCalcCondBatch,
)
def test_clone_model_rejects_non_callable_existing_calc_wrapper() -> None:
"""Existing calc-cond-batch metadata must be callable."""
model = FakeModel({"sampler_calc_cond_batch_function": object()})
with pytest.raises(ValueError, match="Existing sampler_calc_cond_batch_function"):
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
model,
latent_width=8,
latent_height=4,
latent_ndim=4,
regions=(_region(0, 0, 4, 4, "positive", latent_width=8),),
)
def test_existing_calc_wrapper_is_composed_without_recursion() -> None:
"""Fallback and regional calls delegate to the previous calc wrapper."""
calls: list[dict[str, Any]] = []
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Return condition-specific constants and record options."""
calls.append(args)
assert args["model_options"].get("sampler_calc_cond_batch_function") is existing
x = cast(torch.Tensor, args["input"])
conds = cast(list[object], args["conds"])
value = 10.0 if _condition_name(conds[0]) == "global" else 20.0
return [torch.ones_like(x) * value, torch.ones_like(x) * 2.0]
model = FakeModel(
{
"sampler_calc_cond_batch_function": existing,
"model_function_wrapper": object(),
}
)
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
model,
latent_width=4,
latent_height=4,
latent_ndim=4,
regions=(_region(0, 0, 4, 4, "regional"),),
)
)
output = wrapped_model.calc_wrapper(
{
"conds": ["global", "negative"],
"input": torch.zeros((1, 1, 4, 4)),
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert len(calls) == 2
assert wrapped_model.model_options["model_function_wrapper"] is not None
assert torch.allclose(output[0], torch.ones((1, 1, 4, 4)) * 20.0)
assert torch.allclose(output[1], torch.ones((1, 1, 4, 4)) * 2.0)
def test_shape_mismatch_delegates_to_original_calc_path() -> None:
"""Unexpected model input spatial shapes are delegated unchanged."""
calls = 0
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Record fallback calls."""
nonlocal calls
calls += 1
x = cast(torch.Tensor, args["input"])
return [x + 5.0, x + 1.0]
model = FakeModel({"sampler_calc_cond_batch_function": existing})
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
model,
latent_width=8,
latent_height=8,
latent_ndim=4,
regions=(_region(0, 0, 4, 4, "regional", latent_width=8, latent_height=8),),
)
)
x = torch.zeros((1, 1, 4, 4))
output = wrapped_model.calc_wrapper(
{
"conds": ["global", "negative"],
"input": x,
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert calls == 1
assert torch.allclose(output[0], x + 5.0)
def test_region_crops_bchw_final_spatial_axes() -> None:
"""Regional calls crop only final height and width axes."""
calls: list[torch.Tensor] = []
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Record regional input crops."""
x = cast(torch.Tensor, args["input"])
calls.append(x)
conds = cast(list[object], args["conds"])
value = 1.0 if _condition_name(conds[0]) == "global" else 3.0
return [torch.ones_like(x) * value, torch.zeros_like(x)]
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
FakeModel({"sampler_calc_cond_batch_function": existing}),
latent_width=8,
latent_height=4,
latent_ndim=4,
regions=(_region(0, 0, 8, 4, "regional", latent_width=8),),
)
)
x = torch.arange(32, dtype=torch.float32).reshape((1, 1, 4, 8))
output = wrapped_model.calc_wrapper(
{
"conds": ["global", "negative"],
"input": x,
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert calls[1].shape == (1, 1, 4, 8)
assert torch.equal(calls[1], x)
assert torch.allclose(output[0], torch.ones((1, 1, 4, 8)) * 3.0)
def test_region_crops_singleton_depth_5d_final_spatial_axes() -> None:
"""Anima-style regions crop only final height and width axes."""
calls: list[torch.Tensor] = []
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Record regional input crops."""
x = cast(torch.Tensor, args["input"])
calls.append(x)
conds = cast(list[object], args["conds"])
value = 1.0 if _condition_name(conds[0]) == "global" else 4.0
return [torch.ones_like(x) * value, torch.zeros_like(x)]
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
FakeModel({"sampler_calc_cond_batch_function": existing}),
latent_width=8,
latent_height=4,
latent_ndim=5,
regions=(_region(0, 0, 8, 4, "regional", latent_width=8),),
)
)
x = (
torch.arange(128, dtype=torch.float32)
.reshape((1, 16, 1, 4, 2))
.repeat(1, 1, 1, 1, 4)
)
output = wrapped_model.calc_wrapper(
{
"conds": ["global", "negative"],
"input": x,
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert calls[1].shape == (1, 16, 1, 4, 8)
assert torch.equal(calls[1], x)
assert output[0].shape == x.shape
def test_overlapping_regions_normalize_by_accumulated_weight() -> None:
"""Overlapping regions are averaged before blending over fallback."""
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Return different constants for each region positive."""
x = cast(torch.Tensor, args["input"])
cond = _condition_name(cast(list[object], args["conds"])[0])
values = {"global": 0.0, "first": 2.0, "second": 6.0}
return [torch.ones_like(x) * values[cond], torch.zeros_like(x)]
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
FakeModel({"sampler_calc_cond_batch_function": existing}),
latent_width=6,
latent_height=4,
latent_ndim=4,
regions=(
_region(0, 0, 4, 4, "first", latent_width=6),
_region(2, 0, 4, 4, "second", latent_width=6),
),
)
)
output = wrapped_model.calc_wrapper(
{
"conds": ["global", "negative"],
"input": torch.zeros((1, 1, 4, 6)),
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert torch.allclose(output[0][:, :, :, :2], torch.ones((1, 1, 4, 2)) * 2.0)
assert torch.allclose(output[0][:, :, :, 2:4], torch.ones((1, 1, 4, 2)) * 4.0)
assert torch.allclose(output[0][:, :, :, 4:], torch.ones((1, 1, 4, 2)) * 6.0)
def test_partial_mask_blends_region_over_fallback() -> None:
"""Feathered masks blend region predictions with fallback predictions."""
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Return fallback or regional constants."""
x = cast(torch.Tensor, args["input"])
cond = _condition_name(cast(list[object], args["conds"])[0])
value = 10.0 if cond == "global" else 20.0
return [torch.ones_like(x) * value, torch.zeros_like(x)]
mask = torch.ones((4, 4)) * 0.25
region = LatentRegion(
index=0,
label="soft",
latent_box=LatentBox(0, 0, 4, 4),
latent_mask=mask,
positive=_raw_conditioning("regional"),
)
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
FakeModel({"sampler_calc_cond_batch_function": existing}),
latent_width=4,
latent_height=4,
latent_ndim=4,
regions=(region,),
)
)
output = wrapped_model.calc_wrapper(
{
"conds": ["global", "negative"],
"input": torch.zeros((1, 1, 4, 4)),
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert torch.allclose(output[0], torch.ones((1, 1, 4, 4)) * 12.5)
def test_raw_region_conditioning_is_converted_before_calc_cond_batch(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Raw CONDITIONING entries are converted before Comfy calc-cond-batch calls."""
calls: list[list[list[dict[str, Any]] | None]] = []
def calc_cond_batch(
_model: object,
conds: list[list[dict[str, Any]] | None],
x_in: torch.Tensor,
_timestep: torch.Tensor,
_model_options: dict[str, Any],
) -> list[torch.Tensor]:
"""Return constants while asserting sampler-ready conditioning shape."""
calls.append(conds)
first_cond = conds[0]
assert first_cond is not None
assert isinstance(first_cond[0], dict)
assert "model_conds" in first_cond[0]
value = 5.0 if "cross_attn" in first_cond[0] else 1.0
return [torch.ones_like(x_in) * value, torch.zeros_like(x_in)]
fake_samplers = SimpleNamespace(
calc_cond_batch=calc_cond_batch,
resolve_areas_and_cond_masks_multidim=lambda *_args: None,
calculate_start_end_timesteps=lambda *_args: None,
)
monkeypatch.setattr(
regional_multidiffusion_sampling,
"_comfy_samplers",
lambda: fake_samplers,
)
raw_region_positive = [[torch.ones((1, 1, 1)), {}]]
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
FakeModel(),
latent_width=4,
latent_height=4,
latent_ndim=4,
regions=(_region(0, 0, 4, 4, raw_region_positive),),
)
)
output = wrapped_model.calc_wrapper(
{
"conds": [
[{"model_conds": {}, "uuid": object()}],
[{"model_conds": {}, "uuid": object()}],
],
"input": torch.zeros((1, 1, 4, 4)),
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert len(calls) == 2
assert "cross_attn" in cast(list[dict[str, Any]], calls[1][0])[0]
assert torch.allclose(output[0], torch.ones((1, 1, 4, 4)) * 5.0)
def test_global_prompt_weight_blends_full_region_with_global_prediction() -> None:
"""Covered pixels keep the configured global positive prediction share."""
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Return fallback or regional constants."""
x = cast(torch.Tensor, args["input"])
cond = _condition_name(cast(list[object], args["conds"])[0])
value = 10.0 if cond == "global" else 20.0
return [torch.ones_like(x) * value, torch.zeros_like(x)]
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
FakeModel({"sampler_calc_cond_batch_function": existing}),
latent_width=4,
latent_height=4,
latent_ndim=4,
regions=(_region(0, 0, 4, 4, "regional"),),
global_prompt_weight=0.25,
)
)
output = wrapped_model.calc_wrapper(
{
"conds": ["global", "negative"],
"input": torch.zeros((1, 1, 4, 4)),
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert torch.allclose(output[0], torch.ones((1, 1, 4, 4)) * 17.5)
def test_global_prompt_weight_keeps_partial_mask_coverage() -> None:
"""Soft masks scale regional influence before global/regional weighting."""
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Return fallback or regional constants."""
x = cast(torch.Tensor, args["input"])
cond = _condition_name(cast(list[object], args["conds"])[0])
value = 10.0 if cond == "global" else 20.0
return [torch.ones_like(x) * value, torch.zeros_like(x)]
region = LatentRegion(
index=0,
label="soft",
latent_box=LatentBox(0, 0, 4, 4),
latent_mask=torch.ones((4, 4)) * 0.5,
positive=_raw_conditioning("regional"),
)
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
FakeModel({"sampler_calc_cond_batch_function": existing}),
latent_width=4,
latent_height=4,
latent_ndim=4,
regions=(region,),
global_prompt_weight=0.25,
)
)
output = wrapped_model.calc_wrapper(
{
"conds": ["global", "negative"],
"input": torch.zeros((1, 1, 4, 4)),
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert torch.allclose(output[0], torch.ones((1, 1, 4, 4)) * 13.75)
def test_overlapping_regions_normalize_before_global_prompt_weight_blend() -> None:
"""Overlaps average region predictions before applying global weight."""
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Return different constants for each condition."""
x = cast(torch.Tensor, args["input"])
cond = _condition_name(cast(list[object], args["conds"])[0])
values = {"global": 10.0, "first": 20.0, "second": 40.0}
return [torch.ones_like(x) * values[cond], torch.zeros_like(x)]
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
FakeModel({"sampler_calc_cond_batch_function": existing}),
latent_width=4,
latent_height=4,
latent_ndim=4,
regions=(
_region(0, 0, 4, 4, "first"),
_region(0, 0, 4, 4, "second"),
),
global_prompt_weight=0.25,
)
)
output = wrapped_model.calc_wrapper(
{
"conds": ["global", "negative"],
"input": torch.zeros((1, 1, 4, 4)),
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert torch.allclose(output[0], torch.ones((1, 1, 4, 4)) * 25.0)
def test_negative_conditioning_is_reused_for_region_unconditional_path() -> None:
"""Regional calls keep the original negative conditioning."""
regional_conds: list[list[object]] = []
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Record all conditioning lists."""
x = cast(torch.Tensor, args["input"])
conds = cast(list[object], args["conds"])
regional_conds.append(conds)
return [torch.ones_like(x), torch.ones_like(x) * 2.0]
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
FakeModel({"sampler_calc_cond_batch_function": existing}),
latent_width=4,
latent_height=4,
latent_ndim=4,
regions=(_region(0, 0, 4, 4, "regional"),),
)
)
wrapped_model.calc_wrapper(
{
"conds": ["global", "negative"],
"input": torch.zeros((1, 1, 4, 4)),
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert [_condition_name(item) for item in regional_conds[1]] == [
"regional",
"negative",
]
def test_cfg_one_none_uncond_still_returns_two_entries() -> None:
"""Comfy's CFG=1 optimization keeps the output list shape stable."""
def existing(args: dict[str, Any]) -> list[torch.Tensor]:
"""Return one tensor per cond slot, even when uncond is None."""
x = cast(torch.Tensor, args["input"])
conds = cast(list[object], args["conds"])
value = 3.0 if _condition_name(conds[0]) == "regional" else 1.0
return [torch.ones_like(x) * value, torch.zeros_like(x)]
wrapped_model, _summary = (
regional_multidiffusion_sampling.clone_model_with_regional_multidiffusion(
FakeModel({"sampler_calc_cond_batch_function": existing}),
latent_width=4,
latent_height=4,
latent_ndim=4,
regions=(_region(0, 0, 4, 4, "regional"),),
)
)
output = wrapped_model.calc_wrapper(
{
"conds": ["global", None],
"input": torch.zeros((1, 1, 4, 4)),
"sigma": torch.tensor([1.0]),
"model": wrapped_model,
"model_options": wrapped_model.model_options,
}
)
assert len(output) == 2
assert torch.allclose(output[0], torch.ones((1, 1, 4, 4)) * 3.0)
assert torch.allclose(output[1], torch.zeros((1, 1, 4, 4)))
def test_sample_rejects_unipc_before_sampler_resolution(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""UniPC sampler names fail before ComfyUI sampler lookup."""
def fail_resolve_sampler(_sampler_name: str) -> FakeSampler:
"""Fail if sampler resolution is reached."""
raise AssertionError("UniPC rejection should happen before sampler resolution")
monkeypatch.setattr(sampling_samplers, "resolve_sampler", fail_resolve_sampler)
with pytest.raises(ValueError, match="not compatible with UniPC"):
regional_multidiffusion_sampling.sample_regional_multidiffusion(
model=FakeModel(),
seed=1,
steps=1,
cfg=1.0,
sampler_name="uni_pc",
scheduler="normal",
positive=[],
negative=[],
latent_image={"samples": torch.zeros((1, 4, 4, 4))},
regions=(_region(0, 0, 4, 4, "regional"),),
denoise=1.0,
global_prompt_weight=0.0,
)
def test_sample_rejects_unsupported_conditioning() -> None:
"""Regional and ControlNet conditioning fail closed."""
with pytest.raises(ValueError, match="regional conditioning or ControlNet"):
regional_multidiffusion_sampling.sample_regional_multidiffusion(
model=FakeModel(),
seed=1,
steps=1,
cfg=1.0,
sampler_name="euler",
scheduler="normal",
positive=[{"area": (4, 4, 0, 0)}],
negative=[],
latent_image={"samples": torch.zeros((1, 4, 4, 4))},
regions=(_region(0, 0, 4, 4, "regional"),),
denoise=1.0,
global_prompt_weight=0.0,
)
def test_sample_delegates_to_comfy_sampling_with_cloned_wrapped_model(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Sampling mirrors KSampler flow while using a wrapped model clone."""
calls: dict[str, Any] = {}
model = FakeModel()
sampler = FakeSampler()
latent_samples = torch.zeros((1, 4, 4, 8), dtype=torch.float32)
fixed_noise = torch.ones_like(latent_samples)
fixed_sigmas = torch.tensor([1.0, 0.0], dtype=torch.float32)
sampled = torch.full_like(latent_samples, 0.25)
latent_image: dict[str, Any] = {
"samples": latent_samples,
"downscale_ratio_spacial": 2,
"kept": "value",
}
monkeypatch.setattr(
sampling_samplers,
"resolve_sampler",
lambda _sampler_name: sampler,
)
monkeypatch.setattr(
sampling_schedulers,
"calculate_sigmas",
lambda **_kwargs: fixed_sigmas,
)
monkeypatch.setattr(
comfy_sample,
"fix_empty_latent_channels",
lambda _model, samples, _downscale_ratio_spacial: samples,
)
monkeypatch.setattr(
comfy_sample,
"prepare_noise",
lambda samples, _seed, _batch_inds=None: fixed_noise,
)
monkeypatch.setattr(latent_preview, "prepare_callback", lambda _model, _steps: None)
monkeypatch.setattr(comfy_utils, "PROGRESS_BAR_ENABLED", False)
def fake_sample_custom(
received_model: FakeModel,
noise: torch.Tensor,
cfg: float,
received_sampler: FakeSampler,
sigmas: torch.Tensor,
positive: object,
negative: object,
latent_image: torch.Tensor,
noise_mask: torch.Tensor | None,
callback: object,
disable_pbar: bool,
seed: int,
) -> torch.Tensor:
"""Record sample_custom arguments."""
calls["sample_custom"] = {
"model": received_model,
"noise": noise,
"cfg": cfg,
"sampler": received_sampler,
"sigmas": sigmas,
"positive": positive,
"negative": negative,
"latent_image": latent_image,
"noise_mask": noise_mask,
"callback": callback,
"disable_pbar": disable_pbar,
"seed": seed,
}
return sampled
monkeypatch.setattr(comfy_sample, "sample_custom", fake_sample_custom)
output = regional_multidiffusion_sampling.sample_regional_multidiffusion(
model=model,
seed=123,
steps=2,
cfg=7.0,
sampler_name="euler",
scheduler="normal",
positive=[{"model_conds": {}}],
negative=[{"model_conds": {}}],
latent_image=latent_image,
regions=(_region(0, 0, 4, 4, [{"model_conds": {}}], latent_width=8),),
denoise=1.0,
global_prompt_weight=0.25,
)
assert output is not latent_image
assert output["samples"] is sampled
assert output["kept"] == "value"
assert "downscale_ratio_spacial" not in output
assert calls["sample_custom"]["model"] is not model
assert calls["sample_custom"]["model"].calc_wrapper is not None
assert calls["sample_custom"]["sampler"] is sampler
assert calls["sample_custom"]["noise"] is fixed_noise
assert calls["sample_custom"]["disable_pbar"] is True
def test_sample_accepts_singleton_depth_5d_latent(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Anima-style singleton-depth latents pass runtime validation."""
def fake_sample_custom(
_model: object,
_noise: torch.Tensor,
_cfg: float,
_sampler: object,
_sigmas: torch.Tensor,
_positive: object,
_negative: object,
latent_image: torch.Tensor,
**_kwargs: object,
) -> torch.Tensor:
"""Return a deterministic sampled latent for shape validation."""
return latent_image + 1.0
model = FakeModel()
sampler = FakeSampler()
latent_samples = torch.zeros((1, 16, 1, 4, 8), dtype=torch.float32)
fixed_sigmas = torch.tensor([1.0, 0.0], dtype=torch.float32)
monkeypatch.setattr(
sampling_samplers,
"resolve_sampler",
lambda _sampler_name: sampler,
)
monkeypatch.setattr(
sampling_schedulers,
"calculate_sigmas",
lambda **_kwargs: fixed_sigmas,
)
monkeypatch.setattr(
comfy_sample,
"fix_empty_latent_channels",
lambda _model, samples, _downscale_ratio_spacial: samples,
)
monkeypatch.setattr(
comfy_sample,
"prepare_noise",
lambda samples, _seed, _batch_inds=None: torch.ones_like(samples),
)
monkeypatch.setattr(latent_preview, "prepare_callback", lambda _model, _steps: None)
monkeypatch.setattr(comfy_utils, "PROGRESS_BAR_ENABLED", True)
monkeypatch.setattr(comfy_sample, "sample_custom", fake_sample_custom)
output = regional_multidiffusion_sampling.sample_regional_multidiffusion(
model=model,
seed=123,
steps=2,
cfg=7.0,
sampler_name="euler",
scheduler="normal",
positive=[{"model_conds": {}}],
negative=[{"model_conds": {}}],
latent_image={"samples": latent_samples},
regions=(_region(0, 0, 4, 4, [{"model_conds": {}}], latent_width=8),),
denoise=1.0,
global_prompt_weight=0.25,
)
assert torch.equal(output["samples"], latent_samples + 1.0)
def _region(
x: int,
y: int,
width: int,
height: int,
positive: object,
*,
latent_width: int = 4,
latent_height: int = 4,
) -> LatentRegion:
"""Return one full-weight latent region."""
if isinstance(positive, str):
positive = _raw_conditioning(positive)
mask = torch.zeros((latent_height, latent_width), dtype=torch.float32)
mask[y : y + height, x : x + width] = 1.0
return LatentRegion(
index=0,
label="region",
latent_box=LatentBox(x, y, width, height),
latent_mask=mask,
positive=positive,
)
def _raw_conditioning(name: str) -> list[list[object]]:
"""Return a raw Comfy CONDITIONING-like value with a visible test name."""
return [[torch.zeros((1, 1, 1), dtype=torch.float32), {"name": name}]]
def _condition_name(conditioning: object) -> str:
"""Return the test-visible name from raw, processed, or sentinel conditioning."""
if isinstance(conditioning, str):
return conditioning
if isinstance(conditioning, list) and conditioning:
first = conditioning[0]
if isinstance(first, dict):
return str(first.get("name", ""))
if (
isinstance(first, list | tuple)
and len(first) > 1
and isinstance(
first[1],
dict,
)
):
return str(first[1].get("name", ""))
return ""