Skip to content

Entry-port fork legs share one turn vertex, producing a starburst instead of a staggered staircase #1831

Description

@pinin4fjords

Problem

When several same-line edges originate at a section's LEFT/RIGHT entry port and fan out to stacked internal stations, they all turn at the same x-coordinate, producing a "starburst" (all legs radiating from one shared vertex) instead of a "staircase" (legs nested as a bundle near the port, peeling off one at a time, each turning at a slightly later x as it passes its own destination row).

The peel-stagger mechanism that produces the correct staircase already exists and works correctly for non-port forks elsewhere on the same map.

Repro

On the nf-core/riboseq map (tests/fixtures/curve_invariant_repros/riboseq_inter_row_corridor.mmd, added by #1817), the four umi_dedup -->|riboseq| {ribotish, ribotricer, rpbp, price} edges all enter orf_calling through its LEFT entry port (orf_calling__entry_left_7 at (30, 565.6)) and every leg turns down at the same x=45:

ribotish:   (30,565.6) -> (45,565.6) -> (75,624.0) -> (122,624.0)
ribotricer: (30,565.6) -> (45,565.6) -> (75,682.4) -> ...
rpbp:       (30,565.6) -> (45,565.6) -> (75,740.8) -> ...
price:      (30,565.6) -> (45,565.6) -> (75,799.2) -> ...

All four share vertex (45, 565.6) — a starburst. There is 92px of horizontal room between the port (x=30) and the first station (x=122), enough for the staircase to stagger the turn-x per leg (as it already does elsewhere on this same map for non-port forks), so this isn't forced by topology.

Root cause

src/nf_metro/layout/routing/intra_handlers.py. _route_diagonal's anti-starburst mechanism (peel_delay = _fused_opening_legs(...) * offset_step, ~line 727) holds shallower legs back a step so their turns nest. But _fused_opening_legs returns 0 whenever src.is_port (~line 654), on the stated assumption (lines 647-649) that "the entry machinery seats the spread of the legs it feeds." No such staircase-seating exists for a LEFT/RIGHT entry port fanning to stacked internal stations — the port exclusion just suppresses the peel-stagger with nothing to replace it.

Relationship to existing issues

Expected

Same-line edges fanning from a shared entry port nest as a nearby bundle and peel off one at a time, each turning at a distinct x as it passes its own destination row — the same staircase pattern already used for non-port forks on this map.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinglayoutLayout engine, phases, ordering (layout/)riboseqFound while authoring the nf-core/riboseq metro maproutingEdge routing (layout/routing/)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions