fix(routing): render true direction:RL serpentine multi-line folds as a clean U - #1202
Merged
Conversation
…kip ci] A horizontal-flow row folding down into an RL return row carrying a 2+-line bundle could not route the fold corner: every fold-corner port combination either aborted in the render curve invariants (bundle flip + non-concentric descend->turn corner) or wrapped back through a section interior. - reversal.py: a horizontal-flow BOTTOM-exit feeding a horizontal TOP entry now marks the receiver (and its row successors) reversed, so the bundle keeps its order through the descend->turn corner and rides the outside of the fold with no crossover. - perp.py: the intra-section drop departs on the same per-line X the up-and-over feeder lands on, so the section boundary stays straight (no S-jog). - ports.py: the RL drop target's trunk shifts so its entry port aligns under the exit column, giving a straight vertical descent into a clean U. Adds the serpentine_rl_bundle topology fixture and gallery entry plus a parametrised invariant test (no abort, concentric corner, bundle order). Fixes #1193 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- unify _drop_targets / _horizontal_drop_targets onto a shared _perp_drop_targets traversal with lanes_run_along_x/y filters, replacing the duplicated edge walk and the raw direction-string tuples (drops a "TB" literal; TB-branch ratchet 23 -> 22) - extract the shared trunk-shift loop into _shift_section_trunk, used by both the TB (_align_drop_target_trunk) and horizontal (_align_horizontal_drop_target) drop-target aligners - tighten the new comments in perp.py and reversal.py Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
|
Render preview is ready for review: This preview shows only the renders that changed compared to |
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
pinin4fjords
added a commit
that referenced
this pull request
Jul 27, 2026
fix(routing): render true direction:RL serpentine multi-line folds as a clean U
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A true boustrophedon serpentine (top row left-to-right, fold straight down on the right edge, return row right-to-left via
%%metro direction: RL) carrying a 2+-line bundle could not render its fold corner: every fold-corner port combination either aborted inassert_render_curve_invariants(bundle flip + non-concentric descend→turn corner) or wrapped back through a section interior. This is the common shape for folding a long nf-core pipeline map that carries a multi-line bundle (surfaced by nf-core/rnadnavar#83).The fold now renders as a clean U: a straight vertical descent down the right edge, with the bundle staying on the outside the whole way round (top, right, then bottom) and no crossover.
Fix
routing/reversal.py— a horizontal-flow (LR/RL) section's BOTTOM exit feeding a horizontal-flow TOP entry now marks the receiver (and its row successors) reversed, just like the existing TB-feeder case. The descend→turn corner reverses bundle order, so the receiver's trunk order continues the fold rather than resetting to declaration order — the bundle rides the outside of the U with no crossover.routing/perp.py— the intra-section drop departs on the same per-line X the up-and-over feeder lands on (the entry port's own offset), so the section boundary stays straight (no S-jog).layout/phases/ports.py— the RL drop target's trunk shifts so its perpendicular entry port aligns under the exit column, giving a straight vertical descent. (A fully-aligned drop into the first station is not possible for a horizontal-flow target — the trunk is horizontal so the drop must turn, and station-as-elbow forbids the port sharing the station's X — so the entry port is the alignment reference.)Regression infra
examples/topologies/serpentine_rl_bundle.mmdfixture +Serpentine Layoutgallery entry (so the CI render-diff tracks it).tests/test_serpentine_rl_bundle.py— asserts the fold renders without abort, the descend→turn corner is concentric, and bundle order is preserved.Refactor (second commit)
Unifies the two near-duplicate drop-target traversals onto a shared
_perp_drop_targets+lanes_run_along_x/yfilters (migrating off raw direction-string tuples; TB-branch ratchet 23→22), and extracts the shared trunk-shift loop into_shift_section_trunk.Test plan
🤖 Generated with Claude Code