Affine Schedule
The curve that decides when the affine hits hard, drawn where you can see it
- affine_schedule
Every affine sampler would work without this node - leave affine_schedule unwired and you get the house curve, ramping up from a fifth of the way through the run to four fifths. Affine Schedule is for when you want to argue with that. It builds a per-step strength curve and, unusually for this kind of plumbing, draws it on the node so you can read the shape before spending GPU time.
It's the least glamorous node in the family and the one that decides whether the result looks deliberate. Timing is most of the craft here: composition is settled early, detail is established in the middle, and the last few steps are the sampler resolving what it already has. Push strength into that last fifth and you're mostly paying for crunch.
How the curve is built
Think of it as four decisions, in order. start and end are where the affine is active, both expressed as a fraction of the run - defaults are 0.2 and 0.8, i.e. skip the opening fifth and the closing fifth. bias places the peak between them: 0.5 is the middle, 0.1 hits hard early and fades out, 0.9 builds slowly to the end. Then curve decides how strength travels between nothing and the peak - ease_in_out_sine is the default smooth swell, linear is a plain ramp, expo and quint sit near zero and then rush. back and elastic overshoot, which is exactly what it sounds like: they push the affine past the max_scale you asked for. Fun; also how you get artifacts you can't explain.
exponent bends the whole thing toward zero - 1.0 leaves the easing as drawn, 2.0 narrows the peak, 0.5 flattens it into a broad plateau, and 0.0 is the nuclear option that pins every active step at full strength. The two offsets are for when you don't want a clean window: start_offset holds some strength from the very first step (0.3 = a third of the affine from the start), end_offset carries it past end to the last step. Negative values work too, which lets you hold a negative scale out of the gate.
preview_steps only affects the drawing - set it to your sampler's step count (20 matches a default run) and the plot is literally what that run will do. It changes nothing about the schedule itself. That distinction matters when you use a run with start_at_step/end_at_step: a slice of a run reads the part of the curve that belongs to it, so the plotted shape over 20 steps is the truth for a 20-step run, not for a 20-of-40 slice.
Output is one thing: affine_schedule, a DICT for the affine_schedule socket on Affine Sampler, KSampler Affine Advanced or Custom Sampler Affine Advanced. One schedule can feed several of them.
Getting it wired
Affine Schedule ──affine_schedule──► Affine Sampler / KSampler Affine Advanced
▲
(preview_steps just changes the drawing)
Defaults are genuinely usable. Start there, change one thing, and look at the plot before you look at the render - a curve you can't describe in a sentence is a curve you won't be able to debug.
Installing it
It's part of WAS Node Suite v3. ComfyUI Manager, search WAS Node Suite v3, install, restart - or, manually:
cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui.git
That's the whole install: no pip packages, no model downloads, no compilation. The pack needs ComfyUI 0.14.0+ (it's written against the newer comfy_api.latest node API) and Python 3.10+. First start writes config.yaml, plus the wildcard, LUT and viewer folders, under <ComfyUI user dir>/was-node-suite/, and takes a beat longer than later starts while Python compiles the pack to bytecode.
Problems you'll actually hit
The curve looks wrong for your run. It's preview_steps, not the schedule. Set it to the step count you're actually going to run and the plot means something.
"I changed the schedule and nothing changed." Check the sampler's affine_interval - at 4, only every fourth step reads the curve, so a narrow peak between those steps can vanish. And check max_scale is off 1.0, which is the no-op default: the curve multiplies a transform, it isn't one.
Overshoot surprise. If you picked back or elastic, you signed up for the affine reaching past max_scale. That's documented, but it's a genuine cause of "this looks burnt and I only set 1.03".
A 2024 tutorial's advice doesn't transfer. If you're following anything written about WAS Node Suite before v3, note the pack was rewritten: it now installs zero packages, so the old OpenCV/InsightFace dependency fights and post-update import failures you'll find in search results belong to the v2 pack, not this one. If you're seeing those, you have the old install.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| start | FLOAT | 0.200–1 | How far into the run the affine begins, as a share of the steps. 0.0 = from the first step, 0.2 = a fifth of the way in, once the composition has settled. |
| end | FLOAT | 0.800–1 | Where it stops, on the same scale. 0.8 leaves the last fifth untouched, which lets the sampler resolve the detail cleanly; 1.0 carries it to the final step. |
| bias | FLOAT | 0.500–1 | Where the peak sits between start and end. 0.5 = the middle, 0.1 = hits hard early then fades, 0.9 = builds slowly to the end. |
| exponent | FLOAT | 1.000–10 | Bends the whole curve towards zero. 1.0 = as the easing draws it, 2.0 = a narrower peak, 0.5 = a broad plateau. 0.0 pins every active step at full strength. |
| start_offset | FLOAT | 0.00-1–1 | Strength held before the curve begins. 0.0 = nothing until start, 0.3 = a third of the affine from the very first step. |
| end_offset | FLOAT | 0.00-1–1 | Strength held after the curve ends. 0.0 = nothing after end, 0.3 = a third of the affine carried to the last step. |
| curve | COMBO | ease_in_out_sine | How the strength travels between nothing and the peak. 'ease_in_out_sine' is a smooth swell; 'linear' is a plain ramp; the 'expo' and 'quint' curves stay near zero then rush; 'back' and 'elastic' overshoot, which pushes past the scale that was asked for. |
| preview_stepsopt | INT | 202–1000 | How many steps the drawn curve is sampled at. 20 matches a default run; set it to the step count of the sampler this feeds and the plot is exactly what that run will do. The schedule itself is unchanged either way. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| affine_schedule | DICT | The curve, for the affine_schedule socket of any Affine sampler. |