Parallel Transport (LRW)
Carry a style direction across latent space
- latent_from
- latent_to
- latent_vector
- metric
- transported_vector
The style-transfer trick this pack is built around lives here. The idea: you find a direction in latent space that means something - "add a hat," "shift the lighting" - via LRW_LatentVectorFromDiff, but that direction was measured at one specific location in latent space, and latent space is curved. Move the vector to a different image and a naive copy of it might point somewhere meaningless. Parallel Transport is the node that carries the vector from where you measured it to where you want to use it, keeping its meaning intact along the way.
How it works
You give it a start latent, an end latent, and the vector you want moved. It computes a geodesic between start and end on your metric, then drags the vector along that path frame by frame using one of two classic algorithms:
- Schild's Ladder - the default pick. Builds the transported vector with a series of parallelogram-ish steps; robust and well-understood.
- Pole Ladder - an alternative that can be more accurate when the path is long but is a bit more sensitive to how you configure it.
n_rungs (default 5) is how many steps the ladder uses along the path. More rungs = more faithful transport, more compute. If the result looks off, nudge this up.
The inputs:
latent_from,latent_to- the source and destination latent points.latent_vector- the direction you're carrying, straight fromLRW_LatentVectorFromDiff.metric- required. FromLRW_VAEDecoderBridgeorLRW_PullbackMetric. No metric, no curved path, and the node will just refuse the wire.method,n_rungs- the ladder algorithm and its resolution.
Output is one transported_vector (a LATENT), which you then add onto your target latent with LRW_ApplyTransportedVector. Full chain: VAEEncode(A), VAEEncode(B) → LRW_LatentVectorFromDiff → LRW_ParallelTransport (with A as latent_from, your target as latent_to) → LRW_ApplyTransportedVector → KSampler. The pack ships a style-transfer example workflow doing exactly this.
Managing expectations
Parallel transport is the mathematically serious node in this pack - it's the one that genuinely can't be replicated with a few standard nodes, and it's the thing the author's latent-riemannian-world package was built to do. But it only shines when the metric is meaningful, which means the expensive pullback-metric path (LRW_VAEDecoderBridge/LRW_PullbackMetric). On the WAN side that's off the table, which is why this node has no WAN counterpart in the pack. Also, transport between very different latents (huge geometry change) is a hard problem even with a good metric; keep experiments to plausible pairs.
Install
Part of comfyui-lrw-nodes by lajjadred. Search the pack in ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/lajjadred/comfyui-lrw-nodes
cd comfyui-lrw-nodes
pip install -r requirements.txt
Restart ComfyUI. Real deps: latent-riemannian-world >= 0.3.0, torch >= 2.4, Python 3.12+. The pack had early registration/import bugs that made nodes show as broken or UNKNOWN - fixed upstream, so git pull + full restart, and make sure you don't have two copies of the pack in custom_nodes. License is BSL-1.1.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| latent_from | LATENT | — | |
| latent_to | LATENT | — | |
| latent_vector | LATENT | — | |
| metric | METRIC | — | |
| method | COMBO | 2 options: PoleLadder, SchildsLadder | |
| n_rungs | INT | 51–20 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| transported_vector | LATENT | — |