Untwisting RoPE
The training-free style transfer that finally works on Z-Image, Flux.2 and Qwen-Image
- model
- rf_inversion
- unofficial_extensions
- model
If you've tried to push a style onto Z-Image, Flux.2 Klein, Anima, or Qwen-Image, you know the exact pain this node exists to fix. IP-Adapter - the old reliable for style and reference conditioning - is mostly an SDXL/Flux-1 era thing, and the modern DiT image models either lack good ports or need you to train a LoRA to get anywhere. Untwisting RoPE is the training-free answer, and this node is the patcher half of it. No extra model downloads, no training, no LoRA. It rewires the attention mechanism while you generate.
The pack is BigStationW's ComfyUI port of the Untwisting RoPE paper ("frequency control for shared attention in DiTs"), and it's a two-node trick: RF Inversion builds a noise-matched path for your reference image, and Untwisting RoPE consumes that path to actually patch the model. This node is the second one. On its own it does nothing useful - it needs the rf_inversion LATENT from its sibling to know what the reference looks like at every denoising step.
How it works
Untwisting RoPE clones your model and patches its attention and RoPE modules. At each denoising step it takes your target latent, looks up the reference latent at the current noise level (the trajectory RF Inversion built), concatenates the two, and lets the target attend to the reference's keys and values. Then it does the "untwisting": it rescales the rotary position frequencies along a curve you control. Low frequencies carry style, high frequencies carry structure, so by scaling them independently it can transfer lighting, color, and texture without making the composition a copy.
Two details worth knowing. The sampler's sigma schedule is captured internally - there is no SIGMAS input to hunt for. And this transfers style, not identity. The launch thread put it plainly: a character stays a character only if your pipeline has proper multi-reference conditioning; for aesthetic transfer this is exactly what you want.
The inputs that matter
Most of these you can leave at defaults for a first pass, but three are worth touching:
modelandrf_inversion- your loaded model, and the LATENT straight out of the RF Inversion node. The RF settings live on that latent, not on this node.low_scale_start/low_scale_end- style strength. Defaults ramp 1 → 3. Crank this for more reference look.high_scale_start/high_scale_end- structure resemblance. Defaults 1 → 0; higher makes the output follow the reference's geometry more closely.beta(default 50) - steepness of the frequency curve. Higher values stop the model from copying the reference too literally.adain_strength(default 0.5) - AdaIN statistics alignment toward the reference.blocks(default0-999) - which attention blocks get patched, e.g.0-8, 28-37.
The optional unofficial_extensions input takes the UNTWISTING_ROPE_EXTENSIONS object from the Unofficial Extensions node. The single output is a MODEL - wire it into a CFGGuider → SamplerCustomAdvanced chain, which is exactly how the pack's shipped workflows are laid out.
Installing it
The pack has no requirements file and downloads no models - it's pure Python that rides on ComfyUI's own torch and attention hooks. Through ComfyUI Manager, search "ComfyUi-Untwisting-RoPE". Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/BigStationW/ComfyUi-Untwisting-RoPE
Restart ComfyUI. The example workflows reference two companion packs - ComfyUi-Scale-Image-to-Total-Pixels-Advanced and ComfyUi-TextEncodeEditAdvanced - so grab those too if you load one.
Where people get burned
The number one error, straight from the source code: spatial mismatch. The reference latent must be exactly the same width and height as your output, or the patcher throws a shape error. Rescale your reference to match (that's what the ImageScaleToTotalPixels companion is for). The other classic complaint - a launch-day tensor-size crash - turned out to be a buggy sample workflow the author fixed within days, not the node. If something looks wrong, flip verbose on: it prints the per-step frequency scales, which turns "why is my style weak" from a guess into a number.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| rf_inversion | LATENT | — | |
| beta | FLOAT | 50.000.01–100 | Controls the steepness of the frequency scale curve. Higher values prevent the model from copying the reference image too closely. |
| high_scale_start | FLOAT | 1.00-4–8 | Scale applied to high-frequency components. The higher the value, the more the final image will resemble the structure of the reference image. |
| high_scale_end | FLOAT | 0.00-4–8 | Scale applied to high-frequency components. The higher the value, the more the final image will resemble the structure of the reference image. |
| low_scale_start | FLOAT | 1.00-4–8 | Scale applied to low-frequency components. Controls the strength of the style image. |
| low_scale_end | FLOAT | 3.00-4–8 | Scale applied to low-frequency components. Controls the strength of the style image. |
| adain_strength | FLOAT | 0.500–1 | AdaIN aligns the target style statistics toward the reference. |
| blocks | STRING | 0-999 | Specify block ranges to patch, e.g -> 0-8, 28-37 |
| verbose | BOOLEAN | false | Enable verbose logging. |
| unofficial_extensionsopt | UNTWISTING_ROPE_EXTENSIONS | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| model | MODEL | — |