Same widget, sign now carries direction: positive N = final N steps (tail, refine only -- what every laststeps test so far has used). Negative N = first |N| steps instead -- apply while structure is still forming, then get out of the way and let the untouched rest of the schedule resolve it, instead of the perturbed step being close to the last word on the output. Widget min widened 0 -> -50 (backward compatible: 0 still means every step, existing positive values unchanged). Sweep panel accepts negative laststeps in the config line (e.g. 40-41;noseam;1;-2).
56 lines
1.9 KiB
Python
56 lines
1.9 KiB
Python
"""H3 block repeat / span loop: the step-window that confines the repeat to part of the
|
|
schedule instead of firing on every step. Positive N = final N steps (tail); negative N =
|
|
first |N| steps (head) — see engine_settings.js hint for why both directions exist."""
|
|
import sys
|
|
|
|
import torch
|
|
|
|
sys.path.insert(0, ".")
|
|
from samplers import FunPackLTXAVSceneChainSampler as S # noqa: E402
|
|
|
|
|
|
def _args(step, total=6):
|
|
# sigmas holds N+1 values for N steps; sample_sigmas is the full descending schedule.
|
|
sched = torch.linspace(1.0, 0.0, total + 1)
|
|
return {"transformer_options": {"sample_sigmas": sched, "sigmas": sched[step:step + 1]}}
|
|
|
|
|
|
def test_zero_means_every_step():
|
|
for step in range(6):
|
|
assert S._in_last_steps(_args(step), 0) is True
|
|
|
|
|
|
def test_last_two_of_six():
|
|
hits = [S._in_last_steps(_args(step), 2) for step in range(6)]
|
|
assert hits == [False, False, False, False, True, True]
|
|
|
|
|
|
def test_window_wider_than_schedule_is_every_step():
|
|
assert all(S._in_last_steps(_args(step), 50) for step in range(6))
|
|
|
|
|
|
def test_first_two_of_six():
|
|
hits = [S._in_last_steps(_args(step), -2) for step in range(6)]
|
|
assert hits == [True, True, False, False, False, False]
|
|
|
|
|
|
def test_head_and_tail_are_disjoint_at_the_same_magnitude():
|
|
tail = [S._in_last_steps(_args(step), 2) for step in range(6)]
|
|
head = [S._in_last_steps(_args(step), -2) for step in range(6)]
|
|
assert not any(t and h for t, h in zip(tail, head))
|
|
|
|
|
|
def test_missing_schedule_fails_open():
|
|
assert S._in_last_steps({"transformer_options": {}}, 2) is True
|
|
assert S._in_last_steps({"transformer_options": {}}, -2) is True
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test_zero_means_every_step()
|
|
test_last_two_of_six()
|
|
test_window_wider_than_schedule_is_every_step()
|
|
test_first_two_of_six()
|
|
test_head_and_tail_are_disjoint_at_the_same_magnitude()
|
|
test_missing_schedule_fails_open()
|
|
print("ok")
|